Asterisk 1.8 SIP protocol stack Analysis 2

Source: Internet
Author: User
Tags unsupported

In the previous article, we analyzed the process of registering a message with a sip service. Next we will analyze the process of processing an invite request.

 

From the handle_request_invite entry, the invite request processes the replace Request Header here. If it is replace, it is considered to be consulting. At this time, no new channel is created, but a channel is found (masqued ), in most cases, a new request is created based on invite. Therefore, we will start from here without considering the consulting situation.

 

First, check whether the request is a duplicate request. If (! REQ-> ignore). Next, call check_via to check the via header domain. This function involves NAT traversal. This function resolves the rport header domain parameter. If the via header domain has rport =, the request is marked to contain the rport domain flag, and the maddr = domain existence is checked. If rport = exists, the NAT mode is set to Nat; otherwise, no Nat is configured, And the check_via process ends.

 

Return the invite function. Here, there are two invite cases. If the call-Id already exists, asterisk considers this request to be re-invite (! P-> owner). Otherwise, it is considered as a new invite. There are many stories about re-invite, involving whether Asterisk is b2bua or proxy. Next we will discuss non-re-invite requests.

 

See from printed information

Ast_verbose ("using invite request as basis request-% s/n", p-> callid );

 

Using invite request as basis request-zjriyjzkyzyzzdnjndrmmjhmmmnlnzdmode4ntyzzme.

 

If you enable sip history, you can see that it is called,

Append_history (P, "invite", "new call: % s", p-> callid );

 

Next, call the parse_ OK _contact () function to save the invite contact header field for future response (200 OK, bye, re-invite)

The fullcontact variable saves all cantact header fields for bye, re-invite, and okcontacturi to save URI of ACKs, bye, re-invite.

 

Next, call the following code:

 

If (! P-> lastinvite &&! REQ-> ignore &&! P-> owner) {// brand new invite
/* This is a new invite */
/* Handle authentication if this is our first invite */
Int cc_recall_core_id =-1;
Set_pvt_allowed_methods (p, req );
Res = check_user_full (p, req, sip_invite, E, xmit_reliable, ADDR, & authpeer );
If (RES = auth_challenge_sent ){
P-> invitestate = inv_completed;/* needs to restart in another invite transaction */
Res = 0;
Goto request_invite_cleanup;
}

 

For the first request, verification will be performed. Call check_user_full. Next, analyze this function.

 

This function matches the USR name of the request's From header field with the peer's IP/port, and check_user_full calls get_calleridname to extract from the From header field

 

Cal1__name, and finally call check_peer_ OK to check whether the peer name exists in the peers linked list. Try it here

If the user name in the From header field is not found, use IP/port.

The output is as follows.

If (Debug)
Ast_verbose ("found peer '% s' for' % s' from % s/n ",
Peer-> name, of, ast_sockaddr_stringify (& P-> Recv ));

 

 

Found peer '000000' for '000000' from 10.10.10.84: 1501159973

Copy the peer attributes to the channle created for the peer, such as ACC, language, and amaflags. Callgroup, fullcontact, etc,

 

Set a timer to manage transactions...

 

Next, call the dialog_initialize_rtp function to initialize the RTP information of the peer.

 

Whether the peer has RTP. If yes, the encoding is set. When setting the RTP engine, it must be noted that the RTP protocol stack was greatly changed at the beginning of asterisk1.8. By default, the RTP protocol stack provided by asteirsk is used. developers can embed other RTP protocol stacks themselves.

After setting the protocol stack, set the default encoding rules for the Peer to establish the RTP session.

Found peer '000000' for '000000' from 10.10.10.84: 1501159973
[Dec 21 15:30:13] Debug [28437]: rtp_engine.c: 344 ast_rtp_instance_new: Using Engine 'asterisk' for RTP instance '0xc1c0078'
[Dec 21 15:30:13] Debug [28437]: res_rtp_asterisk.c: 472 ast_rtp_new: allocated port 18084 for RTP instance '0xc1c0078'
[Dec 21 15:30:13] Debug [28437]: rtp_engine.c: 353 ast_rtp_instance_new: RTP instance '0xc1c0078 'is setup and ready to go
[Dec 21 15:30:13] Debug [28437]: res_rtp_asterisk.c: 2370 ast_rtp_prop_set: Setup RTCP on RTP instance '0xc1c0078'

 

Route: check_peer_ OK-> dialog_initialize_rtp-> ast_rtp_instance_new-> ast_rtp_instance_set_timeout

Ast_rtp_instance_set_hold_timeout

Ast_rtp_instance_set_prop

 

Ast_rtp_instance_set_qos

 

Do_setnat

 

The above is a call process for some columns, which initializes the RTP information of this peer, including QoS, Nat mode, RTCP, and DTMF tasks. The check_peer_ OK function has done a lot of work ....

 

 

Now that the verification is passed, the RTP information is initialized, And the handl_request_invite function is returned to start processing SDP ....

 

 

/* We have a successful authentication, process the SDP portion if there is one */
If (find_sdp (req )){

If (process_sdp (p, req, sdp_t38_initiate )){
/* Asterisk does not yet support any content-encoding methods. Always
* Attempt to process the SDP, but returned a 415 if a content-encoding header
* Was present after processing fails .*/
If (! Ast_strlen_zero (get_header (req, "content-encoding "))){
Transmit_response_reliable (P, "415 unsupported media type", req );
} Else {
/* Unacceptable codecs */
Transmit_response_reliable (P, "488 not acceptable here", req );
}

....

 

As you can see, start processing SDP...

First of all, you need to find the SDP from the invite request, and call find_sdp (),

 

/*!
/Brief returns whether SDP information exists in the sip invite request package,

*/
Static int find_sdp (struct sip_request * req)

 

Of course we found it here ..

Call process_sdp to process SDP,

/*! /Brief process sip sdp offer, select formats and activate RTP Channels
If offer is rejected, we will not change any properties of the call
Return 0 on success, a negative value on errors.
Must be called after find_sdp ().
*/
Static int process_sdp (struct sip_pvt * P, struct sip_request * req, int t38action)

 

 

Parse the SDP header...

 

[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8197 process_sdp: Processing session-level sdp v = 0... unsupported.
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8197 process_sdp: Processing session-level SDP o =-0 2 in ip4 10.10.10.84... unsupported.
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8197 process_sdp: Processing session-level sdp s = counterpath X-Lite 3. 0... unsupported.
[Dec 21 15:30:13] Debug [28437]: netsock2.c: 125 ast_sockaddr_split_hostport: splitting '10. 10.10.84 'gives...
[Dec 21 15:30:13] Debug [28437]: netsock2.c: 155 ast_sockaddr_split_hostport:... host '10. 10.10.84 'and port' (null )'.
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8197 process_sdp: Processing session-level SDP c = in ip4 10.10.10.84... OK.
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8197 process_sdp: Processing session-level sdp t = 0 0... unsupported.

 

First scan the M = header domain, media stream

 

The following describes some SDP information.

SDP data from example

SDP Parameter

Parameter Name

V = 0

Version Number

O = Tesla 2890844526 2890844526 in ip4 lab.high-voltage.org

Origin containing name

S = phone call

Subject

C = in ip4 100.101.102.103

Connection

T = 0 0

Time

M = audio49170 RTP/AVP 0

Media

A = rtpmap: 0 PCMU/8000

Attributes

  • Connection IP address (100.101.102.103 );

  • Media Format (audio );

  • Port Number (49170 );

  • Media Transport Protocol (RTP );

  • Media Encoding (PCM μ law );

  • Sampling Rate (8,000Hz ).

 

Each SDP header field contains M, O, C, and other processing of different SDP header fields,

Process_sdp _ type function processing is called for each type,

For example, if the connection address processing function process_sdp_c, the most important thing here is the process_sdp_a _ media type. This function processes the attributes of the SDP package, such as audio

Process_sdp_a_audio: the core location of SDP processing is in this function... Process_sdp matches the supported encoding types based on the SDP package attributes (Media Encoding type.

 

[Dec 21 15:30:13] Debug [28437]: rtp_engine.c: 535 ast_rtp_codecs_payloads_set_m_type: Setting payload 98 Based on M type on 0xb7b30490
Found RTP audio format 8
[Dec 21 15:30:13] Debug [28437]: rtp_engine.c: 535 ast_rtp_codecs_payloads_set_m_type: Setting payload 8 Based on M type on 0xb7b30490
Found RTP audio format 101
[Dec 21 15:30:13] Debug [28437]: rtp_engine.c: 535 ast_rtp_codecs_payloads_set_m_type: Setting payload 101 Based on M type on 0xb7b30490
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = alt: 1 1: bwd30 + 5D c9ddg2tq 10.10.10.84 50946... unsupported.
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = fmtp: 101 0-15... unsupported.
Found audio description format bv32 for ID 107
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = rtpmap: 107 bv32/16000... OK.
Found audio description format BV32-FEC for ID 119
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = rtpmap: 119 BV32-FEC/16000... OK.
Found audio description format speex for ID 100
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = rtpmap: 100 speex/16000... OK.
Found audio description format SPEEX-FEC for ID 106
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = rtpmap: 106 SPEEX-FEC/16000... OK.
Found audio description format SPEEX-FEC for ID 105
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = rtpmap: 105 SPEEX-FEC/8000... OK.
Found audio description format ilbc for ID 98
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = rtpmap: 98 ilbc/8000... OK.
Found audio description format telephone-event for ID 101
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = rtpmap: 101 telephone-event/8000... OK.
[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 8384 process_sdp: Processing media-level (audio) sdp a = sendrecv... OK.

 

 

 

So far, the SDP information and RTP information of this peer have been initialized.

 

Return to handle_request_invite ()

/* Check number of concurrent cballs-vs-incoming limit here */
Ast_debug (1, "Checking SIP call limits for device % s/n", p-> username );

 

Start checking the call-limit of peer

If the peer reaches the upper limit, the system returns the 480 temporarily unavailable (call limit) response... So when the response is returned during debugging, we should guess that this device has reached the concurrency limit ....

 

Next, call get_destination (). Where should we send this request ????

This function uses the to header field requested by invite as the request address,

Check whether the requested peerr is in my check_sip_domain () according to the requested peer name @ IP ()... If no result is found, go to dialplan to find .....

 

 

/* If we don't have a peer (I. e. We're a guest call ),
* Overwrite the original context */
If (! Ast_test_flag (& P-> flags [1], sip_page2_havepeercontext )&&! Ast_strlen_zero (domain_context )){
Ast_string_field_set (p, context, domain_context );
}

 

Here, when we set the run guest invite in the SIP config, set context to the default value ..

 

When the corresponding extension is found in dialplan, we need to create a channle for this SIP request ..

 

Call sip_new ()... here, the sip_new function is the place where the SIP Channel is actually created. This function is called in the inbound request and in the outbound call request, namely the sip_request_call and handle_request_invite functions...

 

The sip_new function uses the sip_pvt structure to create a sip uer, and sets the encoding type, dtfm, and caller ID of this channel...

Call the ast_channel_alloc macro (Channel. c) to create the SIP channle. In the _ ast_channel_alloc_ap function, use

The ao2_alloc function also specifies the release channel of the destructor. After applying for channel memory, set the initial status of the pipeline handle and create the context of the channle scheduler,

1.8 The caller party information statistics are added. Therefore, initialize these structures first, and then apply for the channel named channle,

If (pipe (TMP-> alertpipe )){
Ast_log (log_warning, "channel allocation failed: can't create alert pipe! Try increasing Max file descriptors with ulimit-n/n ");
Return ast_channel_unref (TMP );
} Else {
Flags = fcntl (TMP-> alertpipe [0], f_getfl );
If (fcntl (TMP-> alertpipe [0], f_setfl, flags | o_nonblock) <0 ){
Ast_log (log_warning, "channel allocation failed: unable to set alertpipe nonblocking! (% D: % s)/n ", errno, strerror (errno ));
Return ast_channel_unref (TMP );
}
Flags = fcntl (TMP-> alertpipe [1], f_getfl );
If (fcntl (TMP-> alertpipe [1], f_setfl, flags | o_nonblock) <0 ){
Ast_log (log_warning, "channel allocation failed: unable to set alertpipe nonblocking! (% D: % s)/n ", errno, strerror (errno ));
Return ast_channel_unref (TMP );
}
}

 

Add the created MPs queue to the FD list listener .... The number of channle FD is limited. The maximum number of channle is 10 by default.

 

 

/* Always watch the alertpipe */
Ast_channel_set_fd (TMP, ast_alert_fd, TMP-> alertpipe [0]);
/* And timing pipe */
Ast_channel_set_fd (TMP, ast_timing_fd, TMP-> timingfd );

 

 

Next, initialize uniqueid and linkeid. Here, the uniqueid contains a maximum of 150 characters, including the system name (a maximum of 127 characters), Unix timestamp, and incremental sequence...

 

Initialize the amaflags, accountcode, and context of channle to facilitate billing (CDR ).

 

 

Next, allocate the channle CDR structure and initialize it ..

 

 

TMP-> cdr = ast_cdr_alloc (); // allocate
Ast_cdr_init (TMP-> CDR, TMP); // Initialization
Ast_cdr_start (TMP-> CDR); // set the start time, CDR-> start ..

 

Ast_cel_report_event (TMP, ast_cel_channel_start, null, null); // starts the cdel engine .. Send the channle start event ..

More than 1.8 excel, which is also initialized here .. Put channle into the channles internal server ..

 

After creating channle, send the AMI event newchannel .. Return to create channle to sip_new after completion

 

SIP is a channel type. It is actually created as the ast_channle structure in channle. C. This structure is a multi-channel interface layer ,..

Set sipuri, sipdomain, parkinglot, accountcode, language, and other global data to initialize the FD event. It is worth noting that asterisk 1.8 supports epoll asynchronous Io, in some cases, the system concurrency should be improved a lot.

 

Next, sip_new initializes the JT engine (RTP jitter) for the peer with RTP ),

 

Then, this function calls ast_pbx_start to enter the asterisk kernel .... Ast_pbx_start start a new thread to process this channle ..

After the return, call build_route () to record the record_route header domain. Here, the role is to record the route path as a future request.

 

Ast_debug (2, "% s: New call is still down... trying.../N", C-> name );

 

Now, channle has been created. Send a temporary response... Transmit_provisional_response (P, "100 trying", req, 0 );

 

[Dec 21 15:30:13] Debug [28437]: chan_sip.c: 21609 handle_request_invite: SIP/1501159973-0000000b: New call is still down... trying ..

 

 

 

<--- Transmitting (no Nat) to 10.10.10.84: 59584 --->
Sip/2.0 100 trying
Via: SIP/2.0/udp 10.10.10.84: 59584; branch = z9hG4bK-d87543-7c6375234a299e1c-1 -- d87543-; received = 10.10.10.84; rport = 59584
From: "1501159973" <SIP: 1501159973@10.10.10.182>; tag = e648a101
To: "6969 (softphone)" <SIP: 6969@10.10.10.182>
Call-ID: zjriyjzkyzyzzdnjndrmmjhmmmnlnzdmode4ntyzzme.
CSeq: 2 invite
Server: asterisk PBX 1.8.2-RC1
Allow: Invite, ack, cancel, options, bye, refer, subscribe, publish y, info, publish
Supported: replaces, Timer
Contact: <SIP: 6969@10.10.10.182: 5060>
Content-Length: 0

 

Here, we can see that the via header domain has a larger value than the subscribed Ed and rport, solving Nat penetration...

 

Remember that 100 trying has no SDP information .. Call sequence: sip_xmit <-send_response <-- transmit_response <--- transmit_provisional_response <-- handle_request_response.

 

The next step is to execute dialplan... so far, the request to the incoming system is basically complete.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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.