This article is from csdn lidp and reposted the famous source. Thank you.
For information and technology trends in the VoIP industry, see www.voip123.cn.
For the registration function, Asterisk SIP protocol stack provides two services,
1. Asterisk is used as the SIP client and registered with other sip servers.
2. Asterisk is used as the SIP registration server to save client registration information.
The following describes how to enable the second function from the SIP protocol stack:
The SIP protocol stack is dynamically loaded when the system starts. Therefore, this module can be left empty as needed,
Each dynamic loading module is input by load_module.
Initialize the global parameters and data structure of the SIP protocol stack,
Create a scheduler for the re-sending of SIP messages #
If (! (Sched = ast_sched_context_create ())){
Ast_log (log_error, "unable to create schedcontext context \ n ");
Return ast_module_load_failure;
}
Parse the configuration file sip. conf #
If (reload_config (sip_reloadreason) {/* load the configuration from sip. conf */
Return ast_module_load_decline;
}
Register the external interface (dialplan, Ami, etc.) functions provided by the SIP protocol stack,
/* Register astdata providers */
Ast_data_register_multiple (sip_data_providers, array_len (sip_data_providers ));
/* Register all CLI functions for SIP */
Ast_cli_register_multiple (cli_sip, array_len (cli_sip ));
/* Tell the udptl subdriver that we're here */
Ast_udptl_proto_register (& sip_udptl );
......
.....
Finally, call restart_monitor (); start the SIP protocol stack, create the thread do_monitor, listen (poll) server socket FD,
When an event exists, sipsock_read is called back to read socket data.
The Asterisk SIP protocol stack is only responsible for parsing, forwarding, and re-transmission of SIP messages. It is a single-thread protocol stack. Its design does not follow the layered architecture of the SIP protocol stack,
There is no transaction layer, no state machine, its message re-transmission, request and response transaction matching are all identified through some tags, so it is easy to cause problems, this problem was mentioned in the asterisk 10 plan and proposed a scheme to add the transaction mechanism. Due to the limited architecture, the performance of the Asterisk SIP protocol stack is not very high, however, as a b2bua server that provides the signaling service and uses the media stream, the performance of the SIP protocol stack does not affect the overall concurrency of the system. Unlike the SIP proxy, in this case, the performance of the SIP protocol stack is very high.
The following describes the registration request processing process:
The client initiates a registration request. The SIP package is as follows:
Register SIP: 192.168.1.173 Sip/2.0
Via: SIP/2.0/udp 192.168.11.51: 51917; branch = z9hg4bk1498232830; rport
From: <SIP: 1008@192.168.1.173>; tag = 78421215
To: <SIP: 1008@192.168.1.173>
Contact: <SIP: 1008@192.168.11.51: 51917; Transport = UDP>; expires = 1700; + G. oma. sip-im; Language = "en, FR"; + g.3gpp. smsip; + G. oma. sip-im.large-message; audio; + g.3gpp. mpeg-ref = "Urn % 3aurn-7% 3a3gpp-application.ims.iari.gsma-vs"; + g.3gpp. CS-voice
Call-ID: f9c92870-2103-3504-2526-4623ca8a2357
CSeq: 2028434929 register
Content-Length: 0
Max-forwards: 70
Authorization: Digest username = "1008", realm = "192.168.1.173", Nonce = "", uri = "SIP: 192.168.1.173", response = ""
Allow: Invite, ack, cancel, bye, message, options, sort y, prack, update, refer, Info
Privacy: None
P-access-Network-Info: ADSL; utran-cell-id-3gpp = 00000000
User-Agent: videophone 1.0, copyright 2011 cyclecentury Inc.
P-preferred-Identity: <SIP: 1008@192.168.1.173>
Supported: Path
Sipsock_read is called to receive datagram #
Res = ast_recvfrom (FD, readbuf, sizeof (readbuf)-1, 0, & ADDR );
Construct the request structure and call handle_request_do
This function processes all incoming SIP messages, including SIP requests and responses.
Parse the SIP packet to the sip_request structure to handle basic syntax errors.
If (parse_request (req) =-1) {/* Bad packet, can't parse */
Ast_str_reset (req-> data);/* nulling this out is not a good idea here .*/
Return 1;
}
Handle_incoming continues to process this SIP Message #
If (handle_incoming (p, req, ADDR, & recount, & nounlock) =-1 ){
/* Request failed */
Ast_debug (1, "SIP Message cocould not be handled, bad request: %-70.70s \ n", p-> callid [0]? P-> callid: "<no callid> ");
}
Handle_incoming performs different processing based on the SIP request or response:
/* Find Out sip Method for incoming request */
If (req-> Method = sip_response) {/* response to our request */
/* Ignore means "don't do anything with it" but still have
* Respond appropriately.
* But in this case this is a response already, so we really
* Have nothing to do with this message, and even setting
* Ignore flag is pointless.
*/
.....
.....
/* New SIP request coming in
(Cocould be new request in existing sip dialog as well ...)
*/
P-> method = req-> method;/* Find out which sip method they are using */
Ast_debug (4, "***** received % s (% d)-command in SIP % s \ n", sip_methods [p-> method]. text, sip_methods [p-> method]. ID, CMD );
For registration, follow the request process:
Case sip_subscribe:
Res = handle_request_subscribe (p, req, ADDR, seqno, e );
Break;
Case sip_register:
Res = handle_request_register (p, req, ADDR, e );
Sip_report_security_event (p, req, Res );
Break;
Case sip_info:
If (req-> Debug)
Ast_verbose ("refreshing info! \ N ");
If (! REQ-> ignore)
Handle_request_info (p, req );
Else/* if ignoring, transmit response */
Transmit_response (P, "200 OK", req );
Break;
Handle_request_register (p, req, ADDR, e); process registration requests
Register_verify
Resolve the registered user name and domain name by parsing the to header domain of the register request,
To: <SIP: 1008@192.168.1.173>
1008 as the registered user name. The server searches for the memory and database based on the user name to verify whether the user exists.
Peer = sip_find_peer (name, null, true, findpeers, false, 0 );
Sip_find_peer first finds the user in the memory. The peers container saves all registered users in the memory and queries the database if no user is found.
Users added in SIP. conf are automatically loaded to the peers container at system startup, so they will not find the database,
If the user is not configured in SIP. conf, but the Realtime Engine exists, the sipregs database table will be searched,
The sipregs table can be configured in extconfig. conf.
If (! P & (Realtime | devstate_only )){
P = realtime_peer (peer, ADDR, devstate_only, which_objects );
If (p ){
Switch (which_objects ){
Case findusers:
Realtime_peer queries the database sipregs.
Users configured in SIP. conf will not query the database table sipregs.
After finding the user, verify the user:
Check_auth
For the first registration, the server will return 401, and the response is not verified:
Sip/2.0 401 unauthorized
Via: SIP/2.0/udp 192.168.11.51: 46245; branch = z9hg4bk2992151; received = 192.168.11.51; rport = 46245
From: <SIP: 1008@192.168.1.173>; tag = 736151247
To: <SIP: 1008@192.168.1.173>; tag = as4ecd69d3
Call-ID: c2d7ac1e-3470-4775-4412-efcc3adc261f
CSeq: 1593669719 register
Server: asterisk PBX unknown _ and_probably_unsupported
Allow: Invite, ack, cancel, options, bye, refer, subscribe, Policy
Supported: replaces, Timer
WWW-Authenticate: Digest algorithm = MD5, realm = "asterisk", Nonce = "18522543"
Content-Length: 0
The server adds the WWW-Authenticate header to the SIP message header and uses MD5 verification to set the server's realm and a nonce value.
WWW-Authenticate: Digest algorithm = MD5, realm = "asterisk", Nonce = "183658a0"
After the client receives the 401 authentication, it adds the message header authorization: corresponding field.
Register SIP: 192.168.1.173 Sip/2.0
Via: SIP/2.0/udp 192.168.11.51: 46245; branch = z9hg4bk912864128; rport
From: <SIP: 1008@192.168.1.173>; tag = 736151247
To: <SIP: 1008@192.168.1.173>
Contact: <SIP: 1008@192.168.11.51: 46245; Transport = UDP>; expires = 1700; + G. oma. sip-im; Language = "en, FR"; + g.3gpp. smsip; + G. oma. sip-im.large-message; audio; + g.3gpp. mpeg-ref = "Urn % 3aurn-7% 3a3gpp-application.ims.iari.gsma-vs"; + g.3gpp. CS-voice
Call-ID: c2d7ac1e-3470-4775-4412-efcc3adc261f
CSeq: 1593669718 register
Content-Length: 0
Max-forwards: 70
Authorization: Digest username = "1008", realm = "asterisk", Nonce = "183658a0", uri = "SIP: 192.168.1.173", response = "Authorization", algorithm = MD5
Allow: Invite, ack, cancel, bye, message, options, sort y, prack, update, refer, Info
Privacy: None
P-access-Network-Info: ADSL; utran-cell-id-3gpp = 00000000
User-Agent: videophone 1.0, copyright 2011 cyclecentury Inc.
P-preferred-Identity: <SIP: 1008@192.168.1.173>
Supported: Path
The client needs to copy the nonce value of the server response, realm, and add the username, Uri, and Responce fields.
Authorization: Digest username = "1008", realm = "asterisk", Nonce = "183658a0", uri = "SIP: 192.168.1.173", response = "Authorization", algorithm = MD5
For authentication, b2bua and proxy have different response headers. b2bua such as asterisk has a 401 response, and the message header is www-authenticate,
The client authentication header is authorizatiauthorization,
Proxy authentication is responded by 407, the message header is proxy-authenticate, and the client authentication header is roxy-authorization.
After successful authentication, the server returns a OK response to the client. The contact header indicates the address of the client saved by the server, if a call is sent to the client server at a certain time point, the client sends a request based on the address.
Sip/2.0 200 OK
Via: SIP/2.0/udp 192.168.11.51: 46245; branch = z9hg4bk912864128; received = 192.168.11.51; rport = 46245
From: <SIP: 1008@192.168.1.173>; tag = 736151247
To: <SIP: 1008@192.168.1.173>; tag = as3c639d14
Call-ID: c2d7ac1e-3470-4775-4412-efcc3adc261f
CSeq: 1593669718 register
Server: asterisk PBX unknown _ and_probably_unsupported
Allow: Invite, ack, cancel, options, bye, refer, subscribe, Policy
Supported: replaces, Timer
Expires: 1700
Contact: <SIP: 1008@192.168.11.51: 46245; Transport = UDP>; expires = 1700
Date: Tue, 20 Mar 2012 02:16:00 GMT
Content-Length: 0
After the client is successfully registered, the server adds the expires parameter to the contact header or the expire header to indicate the validity period of the registration,
After this time, the server will destroy the validity of this registration. Therefore, after successful registration, the client must enable the periodic registration function and initiate registration at the specified time every expires. This is usually implemented through a timer.