<html>
<head>
    <base href="https://wiki.asterisk.org/wiki">
            <link rel="stylesheet" href="/wiki/s/en/2176/25/9/_/styles/combined.css?spaceKey=AST&amp;forWysiwyg=true" type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://wiki.asterisk.org/wiki/display/AST/res_sip+design">res_sip design</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://wiki.asterisk.org/wiki/display/~mmichelson">Mark Michelson</a>
    </h4>
        <br/>
                         <h4>Changes (70)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. Service registration <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{newcode:language=c} <br>/*! <br> * \brief Register a SIP service in Asterisk. <br> * <br> * This is more-or-less a wrapper around pjsip_endpt_register_module(). <br> * Registering a service makes it so that PJSIP will call into the <br> * service at appropriate times. For more information about PJSIP module <br> * callbacks, see the PJSIP documentation. Asterisk modules that call <br> * this function will likely do so at module load time. <br> * <br> * \param module The module that is to be registered with PJSIP <br> * \retval 0 Success <br> * \retval -1 Failure <br> */ <br>int ast_sip_register_service(pjsip_module *module); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_register_service(pjsip_module *module)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * This is the opposite of ast_sip_register_service().  Unregistering a <br> * service means that PJSIP will no longer call into the module any more. <br> * This will likely occur when an Asterisk module is unloaded. <br> * <br> * \param module The PJSIP module to unregister <br> */ <br>void ast_sip_unregister_service(pjsip_module *module); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This is more-or-less a wrapper around pjsip_endpt_register_module() except that it also adds the module to a container. Registering a service makes it so that PJSIP will call into the service at appropriate times. For more information about PJSIP module callbacks, see the PJSIP documentation. Asterisk modules that call this function will likely do so at module load time. As such, it is important that amongst SIP modules, res_sip should load before others. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">struct ast_sip_authenticator { <br>    int (*requires_authentication)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata); <br>    int (*authenticate_request)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata); <br>    int (*get_authentication_credentials)(struct sip_digest_challenge_data *challenge); <br>}; <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{void ast_sip_unregister_service(pjsip_module *module)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Register a SIP authenticator <br> * <br> * An authenticator has three main purposes: <br> * 1) Determining if authentication should be performed on an incoming request <br> * 2) Gathering credentials necessary for issuing an authentication challenge <br> * 3) Authenticating a request that has credentials <br> * <br> * Asterisk provides a default authenticator, but it may be replaced by a <br> * custom one if desired. <br> * <br> * \param auth The authenticator to register <br> * \retval 0 Success <br> * \retval -1 Failure <br> */ <br>int ast_sip_register_authenticator(struct ast_sip_authenticator *auth); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This is the opposite of ast_sip_register_service().  Unregistering a service means that PJSIP will no longer call into the module any more. This will likely occur when an Asterisk module is unloaded. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Unregister a SIP authenticator <br> * <br> * When there is no authenticator registered, requests cannot be challenged <br> * or authenticated. <br> * <br> * \param auth The authenticator to unregister <br> */ <br>void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_register_authenticator(struct ast_sip_authenticator *auth)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">struct ast_sip_endpoint_identifier { <br>    struct ast_sip_endpoint *(*identify_endpoint)(struct pjsip_rx_data *data); <br>}; <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This allows for a module to register itself as a SIP authenticator. An authenticator has three main purposes: <br>1) Determining if authentication should be performed on an incoming request <br>2) Gathering credentials necessary for issuing an authentication challenge <br>3) Authenticating a request that has credentials <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Register a SIP endpoint identifier <br> * <br> * An endpoint identifier&#39;s purpose is to determine which endpoint a given SIP <br> * message has come from. <br> * <br> * Multiple endpoint identifiers may be registered so that if an endpoint <br> * cannot be identified by one identifier, it may be identified by another. <br> * <br> * Asterisk provides two endpoint identifiers. One identifies endpoints based <br> * on the user part of the From header URI. The other identifies endpoints based <br> * on the source IP address. <br> * <br> * \param identifier The SIP endpoint identifier to register <br> * \retval 0 Success <br> * \retval -1 Failure <br> */ <br>int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Asterisk will implement an authenticator by default. Asterisk&#39;s default authenticator module may be replaced with a custom one if an alternate authentication mechanism is desired. <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">/*!</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \brief Unregister a SIP endpoint identifier <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">*</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Unregisters the currently registered authenticator. With no authenticator registered, requests cannot be authenticated. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * This stops an endpoint identifier from being used. <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">*</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \param identifier The SIP endoint identifier to unregister <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">*/</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This allows for a module to register itself as a SIP endpoint identifier. An endpoint identifier&#39;s purpose is to determine which endpoint a given SIP message has come from. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier); <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">{newcode}</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Multiple endpoint identifiers may be registered so that if an endpoint cannot be identified by one identifier, it may be identified by another. <br> <br>Asterisk will provide two different endpoint identifiers by default. The first will identify an endpoint based on the user portion of the From URI. The second will identify an endpoint based on the IP address from which the request was received. <br> <br>h3. {{int ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)}} <br> <br>This stops an endpoint identifier from the being used. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h2. Threadpool usage <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{newcode:language=c} <br>/*! <br> * \brief Create a new SIP work structure <br> * <br> * A SIP work is a means of grouping together SIP tasks. For instance, one <br> * might create a SIP work so that all tasks for a given SIP dialog will <br> * be grouped together. Grouping the work together ensures that the <br> * threadpool will distribute the tasks in such a way so that grouped work <br> * will execute sequentially. Executing grouped tasks sequentially means <br> * less contention for shared resources. <br> * <br> * \retval NULL Failure <br> * \retval non-NULL Newly-created SIP work <br> */ <br>struct ast_sip_work *ast_sip_create_work(void); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{struct ast_sip_work *ast_sip_create_work(void)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Destroy a SIP work structure <br> * <br> * \param work The SIP work to destroy <br> */ <br>void ast_sip_destroy_work(struct ast_sip_work *work); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This creates a new SIP work structure. What is SIP work? It&#39;s a means of grouping together SIP tasks. For instance, one might create a SIP work so that all tasks for a given SIP dialog will be grouped together. Grouping the work together ensures that the threadpool will distribute the tasks in such a way so that grouped work will execute sequentially. Executing grouped tasks sequentially means less contention for shared resources. <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">/*!</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_push_task(struct ast_sip_work *work, int (*sip_task)(void *), void *task_data)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \brief Pushes a task into the SIP threadpool <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">*</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This will push a task into the SIP threadpool. This uses the {{ast_sip_work}} provided to determine how to push the task. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * This uses the SIP work provided to determine how to push the task. <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">*</span> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \param work The SIP work to which the task belongs <br> * \param sip_task The task to execute <br> * \param task_data The parameter to pass to the task when it executes <br> * \retval 0 Success <br> * \retval -1 Failure <br> */ <br>int ast_sip_push_task(struct ast_sip_work *work, int (*sip_task)(void *), void *task_data); <br>{newcode} <br></td></tr>
            <tr><td class="diff-unchanged" >h2. Common SIP methods <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{newcode:language=c} <br>/*! <br> * \brief General purpose method for sending a SIP request <br> * <br> * Its typical use would be to send one-off messages such as an out of dialog <br> * SIP MESSAGE. <br> * <br> * \param method The method of the SIP request to send <br> * \param body The message body for the SIP request <br> * \dlg Optional. If specified, the dialog on which to send the message. Otherwise, the message <br> *      will be sent out of dialog. <br> * \retval 0 Success <br> * \retval -1 Failure <br> */ <br>int ast_sip_send_request(const char *method, const char *body, struct pjsip_dialog *dlg); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_send_request(const char *method, const char *body, struct pjsip_dialog *dlg}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Determine if an incoming request requires authentication <br> * <br> * This calls into the registered authenticator&#39;s requires_authentication callback <br> * in order to determine if the request requires authentication. <br> * <br> * If there is no registered authenticator, then authentication will be assumed <br> * not to be required. <br> * <br> * \param endpoint The endpoint from which the request originates <br> * \param rdata The incoming SIP request <br> * \retval non-zero The request requires authentication <br> * \retval 0 The request does not require authentication <br> */ <br>int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This function is a general-purpose way of sending a SIP request. Its typical use would be to send one-off messages such as an out of dialog SIP MESSAGE or an in-dialog SIP INFO. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Authenticate an inbound SIP request <br> * <br> * This calls into the registered authenticator&#39;s authenticate_request callback <br> * in order to determine if the request contains proper credentials as to be <br> * authenticated. <br> * <br> * If there is no registered authenticator, then the request will assumed to be <br> * authenticated properly. <br> * <br> * \param endpoint The endpoint from which the request originates <br> * \param rdata The incoming SIP request <br> * \retval 0 Successfully authenticated <br> * \retval nonzero Failure to authenticate <br> */ <br>int ast_sip_authenticate_request(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">struct ast_sip_digest_challenge_data { <br>    /* The realm to which the user is authenticating */ <br>    const char *realm; <br>    /* The username and secret to challenge. Can be <br>     * expressed either as plaintext or as an md5 sum <br>     */ <br>    union { <br>        struct plain { <br>            const char *username; <br>            const char *password; <br>        }; <br>        const char *md5; <br>    }; <br>    /* Indicates whether the username and secret is <br>     * expressed in plaintext or as an md5 sum <br>     */ <br>    int is_md5; <br>    /* Optional domain to use in the challenge */ <br>    const char *domain; <br>    /* Optional opaque to use in the challenge */ <br>    const char *opaque; <br>}; <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This calls into an authenticator in order to determine if the request in {{rdata}} from {{endpoint}} requires authentication. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Get authentication credentials in order to challenge a request <br> * <br> * This calls into the registered authenticator&#39;s get_authentication_credentials <br> * callback in order to get credentials required for challenging a request. <br> * <br> * \param[out] challenge The necessary data in order to be able to challenge a request <br> * \retval 0 Success <br> * \retval -1 Failure <br> */ <br>int ast_sip_get_authentication_credentials(struct ast_sip_digest_challenge_data *challenge); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_authenticate_request(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Challenge an inbound SIP request with a 401 <br> * <br> * This method will send an authentication challenge based on the details <br> * given in its parameter <br> * <br> * \param challenge Details to help in constructing a WWW-Authenticate header <br> * \retval 0 Success <br> * \retval -1 Failure <br> */ <br>int ast_sip_challenge_request(struct sip_digest_challenge_data *challenge); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This calls into an authenticator in order to determine if the request in {{rdata}} from {{endpoint}} contains proper credentials as to be authenticated. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Determine the endpoint that has sent a SIP message <br> * <br> * This will call into each of the registered endpoint identifiers&#39; <br> * identify_endpoint() callbacks until one returns a non-NULL endpoint. <br> * <br> * \param rdata The inbound SIP message to use when identifying the endpoint. <br> * \retval NULL No matching endpoint <br> * \retval non-NULL The matching endpoint <br> */ <br>struct ast_sip_endpoint *ast_sip_identify_endpoint(struct pjsip_rx_data *rdata); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_get_authentication_credentials(struct sip_digest_challenge_data *challenge)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">/*! <br> * \brief Add a header to an outbound SIP message <br> * <br> * \param tdata The message to add the header to <br> * \param name The header name <br> * \param value The header value <br> * \retval 0 Success <br> * \retval -1 Failure <br> */ <br>int ast_sip_add_header(struct pjsip_tx_data *tdata, const char *name, const char *value); <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This calls into an authenticator in order to get credentials required for challenging a request. <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">/*</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_challenge_request(struct sip_digest_challenge_data *challenge)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \brief Add a body to an outbound SIP message <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">*</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This method will send a SIP 401 response with the supplied challenge. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * If this is called multiple times, the latest body will replace the current <br> * body. <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">*</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{struct ast_sip_endpoint *ast_sip_identify_endpoint(struct pjsip_rx_data *rdata)}} <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \param tdata The message to add the body to <br> * \param body The message body to add <br> * \retval 0 Success <br> * \retval -1 Failure <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">*/</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">This will call into each of the registered endpoint identifiers until one returns a non-NULL endpoint. The endpoint identifiers must return an endpoint if one can be identified based on the data in {{rdata}}. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">int ast_sip_add_body(struct pjsip_tx_data *tdata, const char *body); <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;"> </span> <span class="diff-added-words"style="background-color: #dfd;">{newcode}</span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">h3. {{int ast_sip_add_header(struct pjsip_tx_data *tdata, const char *name, const char *value)}} <br> <br>This is a generic method for adding a header to a SIP request or response. More specialized modules may offer more specialized functions to add specific headers in case it is easier to express the header some other form than a name-value pair. <br> <br>h3. {{int ast_sip_add_body(struct pjsip_tx_data *tdata, const char *body)}} <br> <br>This is a generic method for adding a body to a SIP request or response. More specialized modules may offer more specialized functions to add a body of a specific form in case it is easier to express the body in some other way than a string. <br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/wiki/images/icons/emoticons/forbidden.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>This page is a work in progress. Please refrain from making comments until this warning has been removed</td></tr></table></div>

<h1><a name="res_sipdesign-Overview"></a>Overview</h1>

<p>res_sip is the decadent dark chocolate core of the new SIP work in Asterisk 12. It is the cockpit of the SIP jet. As such, its contents are those upon which all other SIP modules (and potentially non-SIP modules) will rely. The following describes its design and its public APIs.</p>

<h1><a name="res_sipdesign-Makeup"></a>Makeup</h1>

<p>res_sip can be divided into four overall sections:</p>

<ul>
        <li>service registrar</li>
        <li>SIP threadpool operator</li>
        <li>provider of common SIP methods</li>
        <li>servicer of PJSIP endpoint (i.e. reads incoming SIP messages)</li>
</ul>


<h1><a name="res_sipdesign-Startupprocess"></a>Startup process</h1>

<p>On startup, res_sip will create a threadpool for SIP to use. The threadpool's specifics will be discussed on a separate page. The threadpool will be used for as much of SIP's operation as possible. After starting the threadpool, res_sip will create a PJSIP endpoint and then begin handling incoming requests from the endpoint.</p>

<h1><a name="res_sipdesign-Publicmethods"></a>Public methods</h1>

<h2><a name="res_sipdesign-Serviceregistration"></a>Service registration</h2>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">/*!
 * \brief Register a SIP service in Asterisk.
 *
 * This is more-or-less a wrapper around pjsip_endpt_register_module().
 * Registering a service makes it so that PJSIP will call into the
 * service at appropriate times. For more information about PJSIP module
 * callbacks, see the PJSIP documentation. Asterisk modules that call
 * this function will likely do so at module load time.
 *
 * \param module The module that is to be registered with PJSIP
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_register_service(pjsip_module *module);

/*!
 * This is the opposite of ast_sip_register_service().  Unregistering a
 * service means that PJSIP will no longer call into the module any more.
 * This will likely occur when an Asterisk module is unloaded.
 *
 * \param module The PJSIP module to unregister
 */
void ast_sip_unregister_service(pjsip_module *module);

struct ast_sip_authenticator {
    int (*requires_authentication)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata);
    int (*authenticate_request)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata);
    int (*get_authentication_credentials)(struct sip_digest_challenge_data *challenge);
};

/*!
 * \brief Register a SIP authenticator
 *
 * An authenticator has three main purposes:
 * 1) Determining if authentication should be performed on an incoming request
 * 2) Gathering credentials necessary for issuing an authentication challenge
 * 3) Authenticating a request that has credentials
 *
 * Asterisk provides a default authenticator, but it may be replaced by a
 * custom one if desired.
 *
 * \param auth The authenticator to register
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_register_authenticator(struct ast_sip_authenticator *auth);

/*!
 * \brief Unregister a SIP authenticator
 *
 * When there is no authenticator registered, requests cannot be challenged
 * or authenticated.
 *
 * \param auth The authenticator to unregister
 */
void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth);

struct ast_sip_endpoint_identifier {
    struct ast_sip_endpoint *(*identify_endpoint)(struct pjsip_rx_data *data);
};

/*!
 * \brief Register a SIP endpoint identifier
 *
 * An endpoint identifier's purpose is to determine which endpoint a given SIP
 * message has come from.
 *
 * Multiple endpoint identifiers may be registered so that if an endpoint
 * cannot be identified by one identifier, it may be identified by another.
 *
 * Asterisk provides two endpoint identifiers. One identifies endpoints based
 * on the user part of the From header URI. The other identifies endpoints based
 * on the source IP address.
 *
 * \param identifier The SIP endpoint identifier to register
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier);

/*!
 * \brief Unregister a SIP endpoint identifier
 *
 * This stops an endpoint identifier from being used.
 *
 * \param identifier The SIP endoint identifier to unregister
 */
void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier);</pre>
</div></div>
<h2><a name="res_sipdesign-Threadpoolusage"></a>Threadpool usage</h2>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">/*!
 * \brief Create a new SIP work structure
 *
 * A SIP work is a means of grouping together SIP tasks. For instance, one
 * might create a SIP work so that all tasks for a given SIP dialog will
 * be grouped together. Grouping the work together ensures that the
 * threadpool will distribute the tasks in such a way so that grouped work
 * will execute sequentially. Executing grouped tasks sequentially means
 * less contention for shared resources.
 *
 * \retval NULL Failure
 * \retval non-NULL Newly-created SIP work
 */
struct ast_sip_work *ast_sip_create_work(void);

/*!
 * \brief Destroy a SIP work structure
 *
 * \param work The SIP work to destroy
 */
void ast_sip_destroy_work(struct ast_sip_work *work);

/*!
 * \brief Pushes a task into the SIP threadpool
 *
 * This uses the SIP work provided to determine how to push the task.
 *
 * \param work The SIP work to which the task belongs
 * \param sip_task The task to execute
 * \param task_data The parameter to pass to the task when it executes
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_push_task(struct ast_sip_work *work, int (*sip_task)(void *), void *task_data);</pre>
</div></div>
<h2><a name="res_sipdesign-CommonSIPmethods"></a>Common SIP methods</h2>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">/*!
 * \brief General purpose method for sending a SIP request
 *
 * Its typical use would be to send one-off messages such as an out of dialog
 * SIP MESSAGE.
 *
 * \param method The method of the SIP request to send
 * \param body The message body for the SIP request
 * \dlg Optional. If specified, the dialog on which to send the message. Otherwise, the message
 *      will be sent out of dialog.
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_send_request(const char *method, const char *body, struct pjsip_dialog *dlg);

/*!
 * \brief Determine if an incoming request requires authentication
 *
 * This calls into the registered authenticator's requires_authentication callback
 * in order to determine if the request requires authentication.
 *
 * If there is no registered authenticator, then authentication will be assumed
 * not to be required.
 *
 * \param endpoint The endpoint from which the request originates
 * \param rdata The incoming SIP request
 * \retval non-zero The request requires authentication
 * \retval 0 The request does not require authentication
 */
int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata);

/*!
 * \brief Authenticate an inbound SIP request
 *
 * This calls into the registered authenticator's authenticate_request callback
 * in order to determine if the request contains proper credentials as to be
 * authenticated.
 *
 * If there is no registered authenticator, then the request will assumed to be
 * authenticated properly.
 *
 * \param endpoint The endpoint from which the request originates
 * \param rdata The incoming SIP request
 * \retval 0 Successfully authenticated
 * \retval nonzero Failure to authenticate
 */
int ast_sip_authenticate_request(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata);

struct ast_sip_digest_challenge_data {
    /* The realm to which the user is authenticating */
    const char *realm;
    /* The username and secret to challenge. Can be
     * expressed either as plaintext or as an md5 sum
     */
    union {
        struct plain {
            const char *username;
            const char *password;
        };
        const char *md5;
    };
    /* Indicates whether the username and secret is
     * expressed in plaintext or as an md5 sum
     */
    int is_md5;
    /* Optional domain to use in the challenge */
    const char *domain;
    /* Optional opaque to use in the challenge */
    const char *opaque;
};

/*!
 * \brief Get authentication credentials in order to challenge a request
 *
 * This calls into the registered authenticator's get_authentication_credentials
 * callback in order to get credentials required for challenging a request.
 *
 * \param[out] challenge The necessary data in order to be able to challenge a request
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_get_authentication_credentials(struct ast_sip_digest_challenge_data *challenge);

/*!
 * \brief Challenge an inbound SIP request with a 401
 *
 * This method will send an authentication challenge based on the details
 * given in its parameter
 *
 * \param challenge Details to help in constructing a WWW-Authenticate header
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_challenge_request(struct sip_digest_challenge_data *challenge);

/*!
 * \brief Determine the endpoint that has sent a SIP message
 *
 * This will call into each of the registered endpoint identifiers'
 * identify_endpoint() callbacks until one returns a non-NULL endpoint.
 *
 * \param rdata The inbound SIP message to use when identifying the endpoint.
 * \retval NULL No matching endpoint
 * \retval non-NULL The matching endpoint
 */
struct ast_sip_endpoint *ast_sip_identify_endpoint(struct pjsip_rx_data *rdata);

/*!
 * \brief Add a header to an outbound SIP message
 *
 * \param tdata The message to add the header to
 * \param name The header name
 * \param value The header value
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_add_header(struct pjsip_tx_data *tdata, const char *name, const char *value);

/*
 * \brief Add a body to an outbound SIP message
 *
 * If this is called multiple times, the latest body will replace the current
 * body.
 *
 * \param tdata The message to add the body to
 * \param body The message body to add
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_add_body(struct pjsip_tx_data *tdata, const char *body);</pre>
</div></div>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;" class="grey">
                        <a href="https://wiki.asterisk.org/wiki/users/removespacenotification.action?spaceKey=AST">Stop watching space</a>
            <span style="padding: 0px 5px;">|</span>
                <a href="https://wiki.asterisk.org/wiki/users/editmyemailsettings.action">Change email notification preferences</a>
</div>
        <a href="https://wiki.asterisk.org/wiki/display/AST/res_sip+design">View Online</a>
        |
        <a href="https://wiki.asterisk.org/wiki/pages/diffpagesbyversion.action?pageId=22085835&revisedVersion=6&originalVersion=5">View Changes</a>
                |
        <a href="https://wiki.asterisk.org/wiki/display/AST/res_sip+design?showComments=true&amp;showCommentArea=true#addcomment">Add Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>