Once started a Service with a name, a callback module and a group of options, it starts listening on a set of transports, ip addresses and ports, and can start receiving requests from other SIP endpoints. For each received request, NkSIP will call specific functions in your callback module. The full list of callback functions is described in Callback Functions and the default implementation of each one is in the nksip_callbacks.erl module.
All of the callback functions are optional, so you only have to implement the functions you need. For example, if you need to perform authentication, you should implement sip_authorize/3. If you don't implement it, no authorization would be done.
Keep in mind that the plugins you activate when starting your service can add new callbacks. See the plugins documentation.
The list of available callback functions is available here.
When a new request or response is received, NkSIP extracts its Call-ID header, and sees if a process to manage that specific call has already been started, sending the request to it to be processed. If it is not yet started, a new one is launched, associated to this specific Call-ID. This process will then start start calling specific functions in the callback module.
Some of these functions allow you to send a response back, while others expect an authorization or routing decision or are called to inform the service about a specific event and don't expect any answer.
In all of the cases, you shouldn't spend a long time inside them, because new requests and retransmissions having the same Call-ID would be blocked until the callback function returns. However, INVITE processing could take a long time (since it can be necessary for the user to manually accept the call), see sip_invite/2 documentation.
Many callback functions receive some of the following arguments:
Request
: represents a full#sipmsg{}
structure.Call
: represents the full#call{}
process state.Dialog
: represents a specific dialog (#dialog{}
) associated to this request.Subscription
: represents a specific subscription (#subscription{}
) associated to a specific dialog.
In all cases you should use the functions in API to extract information from these objects and not use them directly, as its type can change in the future. In case you need to spawn a new process, it is recommended that you don't pass any of these objects to the new process, as they are quite heavy. You should extract a handler for each of them (using the corresponding get_handle()
function) and pass it to the new process.
A typical call order would be the following:
- When a request is received having an Authorization or Proxy-Authorization header, sip_get_user_pass/4 is called to check the user`s password.
- NkSIP calls sip_authorize/3 to check if the request should be authorized.
- If authorized, it calls sip_route/5 to decide what to do with the request: proxy, reply or process it locally.
- If the request is going to be processed locally, sip_invite/2, sip_options/2, sip_register/2, etc., are called depending on the incoming method, and the user must send a reply. If the request is a valid CANCEL, belonging to an active INVITE transaction, the INVITE is cancelled and sip_cancel/3 is called. After sending a successful response to an INVITE request, the other party will send an ACK and sip_ack/2 will be called.
- If the request creates or modifies a dialog and/or a SDP session, sip_dialog_update/3 and/or sip_session_update/3 are called.
- If the remote party sends an in-dialog invite (a reINVITE), NkSIP will call sip_reinvite/2 if it is defined, or sip_invite/2 again if not.
Many of the functions in this group allow you to send a response to the incoming request. NkSIP allows you to use easy response codes like busy
, redirect
, etc. Specific responses like authenticate
are used to send an authentication request to the other party. In case you need to, you can also reply any response code, headers, and body. It is also possible to send reliable provisional responses, that the other party will acknowledge with a PRACK request. All of it is handled by NkSIP automatically. The full list of reply options is available here.
NkSIP uses the NkSERVICE (https://github.com/Nekso/nkservice) framework to process services, and it offers some callbacks on its own.
Under the hood, each started service starts a new standard OTP gen_server process, registered under the same internal name of the service. See start a Service.