Receiving __freeswitch of FreeSWITCH SIP signaling

Source: Internet
Author: User
Tags mutex freeswitch

Processing of FreeSWITCH SIP signaling in Mod_sofia
First, a thread that handles SIP messages is created inside the module's load (mod_sofia_load):

    /* Start one message thread
    /switch_log_printf (Switch_channel_log, Switch_log_info, "starting initial message Thread.\n ");
    Sofia_msg_thread_start (0);

The Config_sofia function is then called.

    if (Config_sofia (Sofia_config_load, NULL)!= switch_status_success) {
        mod_sofia_globals.running = 0;
        return switch_status_generr;
    }

Inside this function, you will parse the profile file inside the conf/sip_profiles. For example, we are familiar with the nternal and external file is here to parse. After parsing, naturally produced a corresponding C language inside the sofia_profile_t structure.
When you get the Sofia_profile_t object, the Launch_sofia_profile_thread () function is called

void Launch_sofia_profile_thread (sofia_profile_t *profile)
{
    //switch_thread_t *thread;
    switch_threadattr_t *thd_attr = NULL;

    Switch_threadattr_create (&thd_attr, profile->pool);
    Switch_threadattr_detach_set (thd_attr, 1);
    Switch_threadattr_stacksize_set (thd_attr, switch_thread_stacksize);
    Switch_threadattr_priority_set (thd_attr, switch_pri_realtime);
    Switch_thread_create (&profile->thread, thd_attr, Sofia_profile_thread_run, Profile, profile->pool);

A new thread is created here, and Nua_create () is called in the new thread to create a UA (User agent), and the corresponding socket port (for example, 5060) is created inside the nua_create (). On this port you are listening for SIP messages from other people. When a SIP message is received, the Sofia_event_callback () is recalled for processing.

Profile->nua = Nua_create (profile->s_root,/* Event loop/Sofia_event_callback, /* Callback for processing events/profile,/* Additional data to pass to Callback * /tag_if (! Sofia_test_pflag (Profile, PFLAG_TLS) | |! profile->tls_only, NUTAG_URL (pr Ofile->bindurl)), Ntatag_user_via (1), Tptag_pong2pi
                                  NG (1), Ntatag_tcp_rport (0), Ntatag_tls_rport (0), Nutag_retry_after_enable (0), tag_if (!STRCHR (Profile->sip IP, ': '), Soatag_af (soa_af_ip4_only)), tag_if (s
                                  TRCHR (Profile->sipip, ': '), Soatag_af (soa_af_ip6_only)), Tag_if (SofiA_test_pflag (Profile, Pflag_tls), Nutag_sips_url (Profile->tls_bindurl)), Tag_if (Profile->ws_bindurl, Nutag_ws_url (profile-
                                         >ws_bindurl)), tag_if (Profile->wss_bindurl,
                                         Nutag_wss_url (Profile->wss_bindurl)), tag_if (Profile->tls_cert_dir, Nutag_certificate_dir (Profile->tls_cert_dir)), tag_if (s Ofia_test_pflag (Profile, Pflag_tls) && profile->tls_passphrase, Tptag_ Tls_passphrase (Profile->tls_passphrase)), tag_if (Sofia_test_pflag (profile, PFLAG_TLS)
                                  , Tptag_tls_verify_policy (Profile->tls_verify_policy)), Tag_if (Sofia_test_pflag (Profile, Pflag_tls), Tptag_tls_verify_depth (profile->tls_verify_de
                                         PTH)), tag_if (Sofia_test_pflag (Profile, Pflag_tls), Tptag_tls_verify_date (Profile->tls_verify_date)), Tag_if (Sofia_test_pflag (profil E, Pflag_tls) && profile->tls_verify_in_subjects, tptag_tls_verify_sub 
                                         Jects (profile->tls_verify_in_subjects)), tag_if (Sofia_test_pflag (Profile, Pflag_tls), Tptag_tls_ciphers (Profile->tls_ciphers)), T Ag_if (Sofia_test_pflag (Profile, Pflag_tls), Tptag_tls_version (profile->tls_ver
                        sion)), tag_if (Sofia_test_pflag (Profile, Pflag_tls) && profile->tls_timeout,                 Tptag_tls_timeout (Profile->tls_timeout)), Tag_if (!STRCHR (profile-&gt ; Sipip, ': '), NTATAG_UDP_MTU (65535)), tag_if (so
                                  Fia_test_pflag (Profile, Pflag_disable_srv), Ntatag_use_srv (0)), Tag_if (Sofia_test_pflag (Profile, pflag_disable_naptr), Ntatag_us
                                         E_naptr (0)), tag_if (Sofia_test_pflag (Profile, Pflag_tcp_pingpong), Tptag_pingpong (Profile->tcp_pingpong)), tag_if (Sofia_test_pflag p
                                  Rofile, Pflag_tcp_ping2pong), Tptag_pingpong (Profile->tcp_ping2pong)),
                                         Tag_if (Sofia_test_pflag (Profile, pflag_disable_srv503),
  ntatag_srv_503 (0)),                                Tag_if (Sofia_test_pflag (Profile, pflag_socket_tcp_keepalive), Tptag_socket_keepalive (profile->socket_tcp_keepalive)), tag_if (sofia_tes T_pflag (Profile, pflag_tcp_keepalive), tptag_keepalive (profile->tcp_keepalive) ), Ntatag_default_proxy (profile->outbound_proxy), N Tatag_server_rport (Profile->server_rport_level), Ntatag_client_rport (Profile->clie
                                  Nt_rport_level), Tptag_log (Sofia_test_flag (Profile, Tflag_tport_log)),
                                  Tptag_capt (Sofia_test_flag (profile, tflag_capture)? mod_sofia_globals.capture_server:NULL), Tag_if (Sofia_test_pflag (Profile, pflag_sipcompact), Ntata G_sipflags (Msg_do_compacT)), tag_if (Profile->timer_t1, Ntatag_sip_t1 (PROFILE->TIMER_T1)),
                                  Tag_if (profile->timer_t1x64, ntatag_sip_t1x64 (profile->timer_t1x64)), Tag_if (Profile->timer_t2, Ntatag_sip_t2 (PROFILE->TIMER_T2)), tag_if (profile- >TIMER_T4, Ntatag_sip_t4 (PROFILE->TIMER_T4)), Siptag_accept_str ("APPLICATION/SDP,
                                         Multipart/mixed "), Tag_if (Sofia_test_pflag (Profile, Pflag_no_connection_reuse),   Tptag_reuse (0)), tag_end ()); /* Last tag should always finish the sequence * *

A endpoint is also created after the UA is created, and a callback function such as State_handler,io_routines is bound to this endpoint. State_handler is a state processing function that is invoked when the state of the session in the endpoint changes. Io_routines is a series of commonly used IO operations, such as initiating outbound calls, reading audio data frames, and so on.

    /* Connect my internal structure to the blank pointer passed to me * * *module_interface
    = switch_loadable_module_creat E_module_interface (pool, modname);
    Sofia_endpoint_interface = Switch_loadable_module_create_interface (*module_interface, SWITCH_ENDPOINT_INTERFACE);
    Sofia_endpoint_interface->interface_name = "Sofia";
    Sofia_endpoint_interface->io_routines = &sofia_io_routines;
    Sofia_endpoint_interface->state_handler = &sofia_event_handlers;
    Sofia_endpoint_interface->recover_callback = Sofia_recover_callback;

As mentioned above, when a SIP message is received, Sofia_event_callback () is invoked to process the corresponding message. Here we can see a variety of familiar signaling. We invite an example to analyze. Before that, let's mention an important function:

void Nua_respond (nua_handle_t *nh,
         int status, Char const *phrase,
         tag_type_t tag, tag_value_t value,
         ...)

This function is to send a SIP signaling.
Then go on to the Sofia_event_callback () function, and if the event is of type: Nua_i_invite, the Switch_core_session_request_uuid () is invoked to create a session. If the session is created successfully, a corresponding Tech_pvt object is also created.

        if (Sofia_test_pflag (profile, Pflag_callid_as_uuid)) {Session
            = Switch_core_session_request_uuid (Sofia_ Endpoint_interface, Switch_call_direction_inbound, Sof_none, NULL, sip->sip_call_id->i_id);
        else {Session
            = Switch_core_session_request (Sofia_endpoint_interface, Switch_call_direction_inbound, SOF_NONE, NULL);

        if (session) {
            const char *channel_name = NULL;
            TECH_PVT = SOFIA_GLUE_NEW_PVT (session);

Initializes and sets the TECH_PVT structure body. Then call Sofia_glue_attach_private to bind the object to the corresponding session.

            Sofia_glue_attach_private (Session, Profile, TECH_PVT, channel_name);

            set_call_id (tech_pvt, SIP);

Finally, call Sofia_queue_message (DE) and put the event in a team to handle some time-consuming operations.

//static int foo = 0; void Sofia_queue_message (sofia_dispatch_event_t *de) {int launch = 0;
        if (mod_sofia_globals.running = = 0 | |!mod_sofia_globals.msg_queue) {sofia_process_dispatch_event (&de);
    Return if (De->profile && sofia_test_pflag (de->profile, Pflag_thread_per_reg) && De->dat A->e_event = = Nua_i_register && de_thread_cnt < mod_sofia_globals.max_reg_threads) {Sofia_process_d
        Ispatch_event_in_thread (&de);
    Return if (Switch_queue_size (Mod_sofia_globals.msg_queue) > (sofia_msg_queue_size * (unsigned int) msg_queue_threads))
    ) {launch++; } if (launch) {if (Mod_sofia_globals.msg_queue_len < mod_sofia_globals.max_msg_queues) {SOF
        Ia_msg_thread_start (Mod_sofia_globals.msg_queue_len + 1);
} switch_queue_push (Mod_sofia_globals.msg_queue, de); }

Here to determine if you need to increase the consumption thread, add it if you want, and then call Switch_queue_push () to push the message to the real message team.
The consumer threads that have just started, the real execution function is: Sofia_msg_thread_run ()

static int count = 0;
    void *switch_thread_func Sofia_msg_thread_run (switch_thread_t *thread, void *obj) {void *pop;
    switch_queue_t *q = (switch_queue_t *) obj;


    int my_id; for (my_id = 0; my_id < Mod_sofia_globals.msg_queue_len; my_id++) {if (mod_sofia_globals.msg_queue_thread[my_i
        D] = = thread) {break;
    } switch_mutex_lock (Mod_sofia_globals.mutex);
    msg_queue_threads++;

    Switch_mutex_unlock (Mod_sofia_globals.mutex);


    switch_log_printf (Switch_channel_log, switch_log_warning, "MSG Thread%d started\n", my_id); for (;;)
            {if (Switch_queue_pop (q, &pop)!= switch_status_success) {switch_cond_next ();
        Continue
            } if (pop) {sofia_dispatch_event_t *de = (sofia_dispatch_event_t *) Pop;
        Sofia_process_dispatch_event (&de);
        } else {break; } switch_log_printf (Switch_channel_log, switch_log_warning, "MSG Thread ended\n ");
    Switch_mutex_lock (Mod_sofia_globals.mutex);
    msg_queue_threads--;

    Switch_mutex_unlock (Mod_sofia_globals.mutex);
return NULL; }

So the actual call is Sofia_process_dispatch_event (), and sofia_process_dispatch_event () actually calls the following: Our_sofia_event_callback () To process the received message. Here we finally see the handling of various events. In the various branches of the switch, we can see many SIP event that begin with Nua_r and nua_i. Where the former identity receives a response (Response) message, which indicates that a request message was received. When you receive a request message:

    Case Nua_i_invite:
        if (Session && sofia_private) {
            if (Sofia_private->is_call > 1) {
                Sofia_ Handle_sip_i_reinvite (Session, Nua, profile, NH, sofia_private, sip, DE, tags);
            else {
                sofia_private->is_call++;
                Sofia_handle_sip_i_invite (Session, Nua, profile, NH, sofia_private, sip, DE, tags);
            }
        Break

Which is called Sofia_handle_sip_i_invite to process.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.