<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_session+design">res_sip_session design</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://wiki.asterisk.org/wiki/display/~mmichelson">Mark Michelson</a>
    </h4>
        <div id="versionComment">
        <b>Comment:</b>
        Addressing Josh's comments from reviewboard.<br />
    </div>
        <br/>
                         <h4>Changes (37)</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>/*! <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \brief Pieces of data associated with a session <br> * <br> * Supplements to SIP sessions may wish to store session-specific <br> * data on the session. They do this by adding cookies to the session <br> * and retrieving them when needed. Session cookies are similar to <br> * channel datastores. <br> */ <br>struct ast_sip_session_cookie { <br>    /*! Callback used to destroy the cookie&#39;s data. Called when the cookie is removed from the session */ <br>    void (*destroy)(void *cookie); <br>    /*! Identifier for the cookie. Used when storing and retrieving a cookie */ <br>    const char *name; <br>    /*! Data associated with the cookie */ <br>    void *cookie_data; <br>}; <br> <br>/*! <br></td></tr>
            <tr><td class="diff-unchanged" > * \brief A structure describing a SIP session <br> */ <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >    /* The Asterisk channel associated with the session */ <br>    struct ast_channel *channel; <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">    /* Cookies added to the session by supplements to the session */ <br>    struct ao2_container *cookies; <br></td></tr>
            <tr><td class="diff-unchanged" >}; <br> <br>/*! <br></td></tr>
            <tr><td class="diff-changed-lines" >* \brief <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">An extension</span> <span class="diff-added-words"style="background-color: #dfd;">A supplement</span> to SIP message processing <br></td></tr>
            <tr><td class="diff-unchanged" > * <br> * These can be registered by any module in order to add <br> * processing to incoming and outgoing SIP requests and responses <br> */ <br></td></tr>
            <tr><td class="diff-changed-lines" >struct <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">ast_sip_session_extension</span> <span class="diff-added-words"style="background-color: #dfd;">ast_sip_session_supplement</span> { <br></td></tr>
            <tr><td class="diff-unchanged" >    /*! Method on which to call the callbacks. If NULL, call on all methods */ <br>    const char *method; <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">    /*! Notification that the session has begun */ <br>    void (*session_begin)(struct ast_sip_session *session); <br>    /*! Notification that the session has ended */ <br>    void (*session_end)(struct ast_sip_session *session); <br>    /*! <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;">* \brief</span> Called on incoming SIP request <br></td></tr>
            <tr><td class="diff-unchanged" >     * This method can indicate a failure in processing in its return. If there <br>     * is a failure, it is required that this method sends a response to the request. <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>/*! <br></td></tr>
            <tr><td class="diff-changed-lines" >* \brief A handler for <span class="diff-changed-words">SDP<span class="diff-added-chars"style="background-color: #dfd;">s</span></span> in SIP <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">INVITEs</span> <span class="diff-added-words"style="background-color: #dfd;">sessions</span> <br></td></tr>
            <tr><td class="diff-unchanged" > * <br> * An SDP handler is registered by a module that is interested in being the <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;"> * responsible party for all aspects SDP. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * responsible party for specific types of SDP streams. <br></td></tr>
            <tr><td class="diff-unchanged" > */ <br>struct ast_sip_session_sdp_handler { <br>    /*! <br></td></tr>
            <tr><td class="diff-changed-lines" >* \brief Set session details based on <span class="diff-added-words"style="background-color: #dfd;">a stream in</span> an incoming SDP <span class="diff-added-words"style="background-color: #dfd;">offer or answer</span> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">     * \param session The session for which the media is being negotiated <br>     * \param stream The stream on which to operate <br>     * \retval 0 The stream was not handled by this handler. If there are other registered handlers for this stream type, they will be called. <br>     * \retval &lt;0 There was an error encountered. No further operation will take place and the current negotiation will be abandoned. <br>     * \retval &gt;0 The stream was handled by this handler. No further handler of this stream type will be called. <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;">    int (*handle_incoming_sdp)(struct ast_sip_session *session, struct pjsip_rx_data *rdata); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">    int (*handle_incoming_sdp_stream_offer)(struct ast_sip_session *session, struct pjmedia_sdp_media *stream); <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;">     * \brief Create an SDP and add it to the outgoing request or response <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">     * \brief Create an SDP media stream and add it to the outgoing SDP offer or answer <br>     * \param session The session for which media is being added <br>     * \param[out] stream The stream to be added to the SDP <br>     * \retval 0 This handler has no stream to add. If there are other registered handlers for this stream type, they will be called. <br>     * \retval &lt;0 There was an error encountered. No further operation will take place and the current SDP negotiation will be abandoned. <br>     * \retval &gt;0 The handler has a stream to be added to the SDP. No further handler of this stream type will be called. <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;">    void (*add_outgoing_sdp)(struct ast_sip_session *session, struct pjsip_tx_data *tdata); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">    int (*create_outgoing_sdp_stream)(struct ast_sip_session *session, struct pjmedia_sdp_session *sdp); <br></td></tr>
            <tr><td class="diff-unchanged" >}; <br>{newcode} <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > * responsible for constructing outgoing SDPs. <br> * <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * Multiple handlers for the same stream type may be registered. They will be <br> * visited in the order they were registered. Handlers will be visited for each <br> * stream type until one claims to have handled the stream. <br> * <br></td></tr>
            <tr><td class="diff-unchanged" > * \param handler The SDP handler to register <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \param stream_type The type of media stream for which to call the handler <br></td></tr>
            <tr><td class="diff-unchanged" > * \retval 0 Success <br> * \retval -1 Failure <br> */ <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">int ast_sip_session_register_sdp_handler(const struct ast_sip_session_sdp_handler *handler); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">int ast_sip_session_register_sdp_handler(const struct ast_sip_session_sdp_handler *handler, const char *stream_type); <br></td></tr>
            <tr><td class="diff-unchanged" > <br>/*! <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>/*! <br></td></tr>
            <tr><td class="diff-changed-lines" >* \brief Register <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">an extension</span> <span class="diff-added-words"style="background-color: #dfd;">a supplement</span> to SIP session processing <br></td></tr>
            <tr><td class="diff-unchanged" > * <br> * This allows for someone to insert themselves in the processing of SIP <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > * a module could reject an incoming request if desired. <br> * <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;"> * \param extension The extension to register <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \param supplement The supplement to register <br></td></tr>
            <tr><td class="diff-unchanged" > * \retval 0 Success <br> * \retval -1 Failure <br> */ <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">int ast_sip_session_register_extension(struct ast_sip_session_extension *extension); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">int ast_sip_session_register_supplement(struct ast_sip_session_supplement *supplement); <br></td></tr>
            <tr><td class="diff-unchanged" > <br>/*! <br></td></tr>
            <tr><td class="diff-changed-lines" >* \brief Unregister a an <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">extension</span> <span class="diff-added-words"style="background-color: #dfd;">supplement</span> to SIP session processing <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;"> * \param extension The extension to unregister <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \param supplement The supplement to unregister <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;">void ast_sip_session_unregister_extension(struct ast_sip_session_extension *extension); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement); <br></td></tr>
            <tr><td class="diff-unchanged" >{newcode} <br>h2. Common SIP methods <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > * \retval -1 Identifying information could not be found <br> */ <br></td></tr>
            <tr><td class="diff-changed-lines" >int ast_sip_session_get_identity(struct <span class="diff-added-words"style="background-color: #dfd;">pjsip_rx_data *rdata, struct</span> ast_party_id *id); <br></td></tr>
            <tr><td class="diff-unchanged" > <br>/*! <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > * This method will inspect the session in order to construct an appropriate <br> * reinvite. As with any outgoing request in res_sip_session, this will <br></td></tr>
            <tr><td class="diff-changed-lines" >* call into registered <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">extensions</span> <span class="diff-added-words"style="background-color: #dfd;">supplements</span> in case they wish to add anything. <br></td></tr>
            <tr><td class="diff-unchanged" > *  <br> * \param session The session on which the reinvite will be sent <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;"> * \param response_cb Optional callback that can be called when the reinvite response is received. The callback is identical in nature to the incoming_response() callback for session supplements. <br></td></tr>
            <tr><td class="diff-unchanged" > * \retval 0 Successfully sent reinvite <br> * \retval -1 Failure to send reinvite <br> */ <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">int ast_sip_session_send_reinvite(struct ast_sip_session *session); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">int ast_sip_session_send_reinvite(struct ast_sip_session *session, int (*response_cb)(struct ast_sip_session *session, struct pjsip_rx_data *rdata)); <br></td></tr>
            <tr><td class="diff-unchanged" > <br>/*! <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > * <br> * This will send a SIP response to the request specified in rdata. This will <br></td></tr>
            <tr><td class="diff-changed-lines" >* call into any registered <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">extensions&#39;</span> <span class="diff-added-words"style="background-color: #dfd;">supplements&#39;</span> outgoing_response callback. <br></td></tr>
            <tr><td class="diff-unchanged" > * <br> * \param session The session to which the current transaction belongs <br></td></tr>
            <tr><td class="diff-snipped" >...<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 currently under construction. Please refrain from adding comments until this warning is removed</td></tr></table></div>

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

<p><tt>res_sip_session</tt> represents the "core" of SIP session operations. In the context of SIP, a "session" refers to a media session, such as a phone call. The SIP channel driver will be a consumer of the services provided by <tt>res_sip_session</tt>.</p>

<h1><a name="res_sip_sessiondesign-Startupprocedure"></a>Startup procedure</h1>

<p>When <tt>res_sip_session</tt> starts up, it registers itself with <tt>res_sip</tt> as a service. This will cause <tt>res_sip</tt> to call into <tt>res_sip_session</tt> when new SIP messages come in. <tt>res_sip_session</tt> will handle those associated with sessions (i.e. INVITEs, and in-dialog REFERs, INFOs, UPDATEs, and PRACKs).</p>

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

<h2><a name="res_sip_sessiondesign-Structures"></a>Structures</h2>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">/*!
 * \brief Pieces of data associated with a session
 *
 * Supplements to SIP sessions may wish to store session-specific
 * data on the session. They do this by adding cookies to the session
 * and retrieving them when needed. Session cookies are similar to
 * channel datastores.
 */
struct ast_sip_session_cookie {
    /*! Callback used to destroy the cookie's data. Called when the cookie is removed from the session */
    void (*destroy)(void *cookie);
    /*! Identifier for the cookie. Used when storing and retrieving a cookie */
    const char *name;
    /*! Data associated with the cookie */
    void *cookie_data;
};

/*!
 * \brief A structure describing a SIP session
 */
struct ast_sip_session {
    /* The endpoint with which Asterisk is communicating */
    struct ast_sip_endpoint *endpoint;
    /* The PJSIP details of the session, which includes the dialog */
    struct pjsip_inv_session *inv_session;
    /* The Asterisk channel associated with the session */
    struct ast_channel *channel;
    /* Cookies added to the session by supplements to the session */
    struct ao2_container *cookies;
};

/*!
 * \brief A supplement to SIP message processing
 *
 * These can be registered by any module in order to add
 * processing to incoming and outgoing SIP requests and responses
 */
struct ast_sip_session_supplement {
    /*! Method on which to call the callbacks. If NULL, call on all methods */
    const char *method;
    /*! Notification that the session has begun */
    void (*session_begin)(struct ast_sip_session *session);
    /*! Notification that the session has ended */
    void (*session_end)(struct ast_sip_session *session);
    /*!
     * \brief Called on incoming SIP request
     * This method can indicate a failure in processing in its return. If there
     * is a failure, it is required that this method sends a response to the request.
     */
    int (*incoming_request)(struct ast_sip_session *session, struct pjsip_rx_data *rdata);
    /*! Called on an incoming SIP response */
    void (*incoming_response)(struct ast_sip_session *session, struct pjsip_rx_data *rdata);
    /*! Called on an outgoing SIP request */
    void (*outgoing_request)(struct ast_sip_session *session, struct pjsip_tx_data *tdata);
    /*! Called on an outgoing SIP response */
    void (*outgoing_response)(struct ast_sip_session *session, struct pjsip_tx_data *tdata);
};

/*!
 * \brief A handler for SDPs in SIP sessions
 *
 * An SDP handler is registered by a module that is interested in being the
 * responsible party for specific types of SDP streams.
 */
struct ast_sip_session_sdp_handler {
    /*!
     * \brief Set session details based on a stream in an incoming SDP offer or answer
     * \param session The session for which the media is being negotiated
     * \param stream The stream on which to operate
     * \retval 0 The stream was not handled by this handler. If there are other registered handlers for this stream type, they will be called.
     * \retval &lt;0 There was an error encountered. No further operation will take place and the current negotiation will be abandoned.
     * \retval &gt;0 The stream was handled by this handler. No further handler of this stream type will be called.
     */
    int (*handle_incoming_sdp_stream_offer)(struct ast_sip_session *session, struct pjmedia_sdp_media *stream);
    /*!
     * \brief Create an SDP media stream and add it to the outgoing SDP offer or answer
     * \param session The session for which media is being added
     * \param[out] stream The stream to be added to the SDP
     * \retval 0 This handler has no stream to add. If there are other registered handlers for this stream type, they will be called.
     * \retval &lt;0 There was an error encountered. No further operation will take place and the current SDP negotiation will be abandoned.
     * \retval &gt;0 The handler has a stream to be added to the SDP. No further handler of this stream type will be called.
     */
    int (*create_outgoing_sdp_stream)(struct ast_sip_session *session, struct pjmedia_sdp_session *sdp);
};</pre>
</div></div>
<h2><a name="res_sip_sessiondesign-Extensibility"></a>Extensibility</h2>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">/*!
 * \brief Register an SDP handler
 *
 * An SDP handler is responsible for parsing incoming SDPs and ensuring that
 * Asterisk can cope with the contents. Similarly, the SDP handler will be
 * responsible for constructing outgoing SDPs.
 *
 * Multiple handlers for the same stream type may be registered. They will be
 * visited in the order they were registered. Handlers will be visited for each
 * stream type until one claims to have handled the stream.
 *
 * \param handler The SDP handler to register
 * \param stream_type The type of media stream for which to call the handler
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_session_register_sdp_handler(const struct ast_sip_session_sdp_handler *handler, const char *stream_type);

/*!
 * \brief Unregister an SDP handler
 *
 * \param handler The SDP handler to unregister
 */
void ast_sip_session_unregister_sdp_handler(const struct ast_sip_session_sdp_handler *handler);

/*!
 * \brief Register a supplement to SIP session processing
 *
 * This allows for someone to insert themselves in the processing of SIP
 * requests and responses. This, for example could allow for a module to
 * set channel data based on headers in an incoming message. Similarly,
 * a module could reject an incoming request if desired.
 *
 * \param supplement The supplement to register
 * \retval 0 Success
 * \retval -1 Failure
 */
int ast_sip_session_register_supplement(struct ast_sip_session_supplement *supplement);

/*!
 * \brief Unregister a an supplement to SIP session processing
 *
 * \param supplement The supplement to unregister
 */
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement);</pre>
</div></div>
<h2><a name="res_sip_sessiondesign-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 Retrieve identifying information from an incoming request
 *
 * This will retrieve identifying information and place it in the
 * id parameter. The caller of the function can then apply this to
 * caller ID, connected line, or whatever else may be proper.
 *
 * \param rdata The incoming request or response
 * \param[out] id The collected identity information
 * \retval 0 Successfully found identifying information
 * \retval -1 Identifying information could not be found
 */
int ast_sip_session_get_identity(struct pjsip_rx_data *rdata, struct ast_party_id *id);

/*!
 * \brief Send a reinvite on a session
 *
 * This method will inspect the session in order to construct an appropriate
 * reinvite. As with any outgoing request in res_sip_session, this will
 * call into registered supplements in case they wish to add anything.
 * 
 * \param session The session on which the reinvite will be sent
 * \param response_cb Optional callback that can be called when the reinvite response is received. The callback is identical in nature to the incoming_response() callback for session supplements.
 * \retval 0 Successfully sent reinvite
 * \retval -1 Failure to send reinvite
 */
int ast_sip_session_send_reinvite(struct ast_sip_session *session, int (*response_cb)(struct ast_sip_session *session, struct pjsip_rx_data *rdata));

/*!
 * \brief Send a SIP response
 *
 * This will send a SIP response to the request specified in rdata. This will
 * call into any registered supplements' outgoing_response callback.
 *
 * \param session The session to which the current transaction belongs
 * \param response_code The response code to send for this response
 * \param rdata The response to which the response is being sent
 */
int ast_sip_session_send_response(struct ast_sip_session *session, int response_code, struct pjsip_rx_data *rdata);</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_session+design">View Online</a>
        |
        <a href="https://wiki.asterisk.org/wiki/pages/diffpagesbyversion.action?pageId=22085841&revisedVersion=9&originalVersion=8">View Changes</a>
                |
        <a href="https://wiki.asterisk.org/wiki/display/AST/res_sip_session+design?showComments=true&amp;showCommentArea=true#addcomment">Add Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>