<html>
 <body>
  <div style="font-family: Verdana, Arial, Helvetica, Sans-Serif;">
   <table bgcolor="#f9f3c9" width="100%" cellpadding="8" style="border: 1px #c9c399 solid;">
    <tr>
     <td>
      This is an automatically generated e-mail. To reply, visit:
      <a href="https://reviewboard.asterisk.org/r/2858/">https://reviewboard.asterisk.org/r/2858/</a>
     </td>
    </tr>
   </table>
   <br />




<table bgcolor="#fefadf" width="100%" cellspacing="0" cellpadding="8" style="background-image: url('https://reviewboard.asterisk.org/static/rb/images/review_request_box_top_bg.png'); background-position: left top; background-repeat: repeat-x; border: 1px black solid;">
 <tr>
  <td>

<div>Review request for Asterisk Developers and Mark Michelson.</div>
<div>By George Joseph.</div>


<p style="color: grey;"><i>Updated Sept. 30, 2013, 3:15 p.m.</i></p>



<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Changes</h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">New patch...
Only 1 function exposed: 'PJSIP_HEADER'.
PLEASE CHECK THE CALLING CONVENTIONS, especially 'remove' which can be called without an assignment.



  -= Info about function 'PJSIP_HEADER' =- 

[Synopsis]
Gets, adds, updates or removes the specified SIP header from a PJSIP session.


[Description]
Examples:
;
; Set 'somevar' to the value of the 'From' header.
exten => 1,1,Set(somevar=PJSIP_HEADER(read,From))
;
; Set 'via2' to the value of the 2nd 'Via' header.
exten => 1,1,Set(via2=PJSIP_HEADER(read,Via,2))
;
; Add an 'X-Myheader' header with the value of 'myvalue'.
exten => 1,1,Set(PJSIP_HEADER(add,X-MyHeader)=myvalue)
;
; Add an 'X-Myheader' header with an empty value.
exten => 1,1,Set(PJSIP_HEADER(add,X-MyHeader)=)
;
; Update the value of the header named 'X-Myheader' to 'newvalue'.
; 'X-Myheader' must already exist or the call will fail.
exten => 1,1,Set(PJSIP_HEADER(update,X-MyHeader)=newvalue)
;
; Remove all headers whose names exactly match 'X-MyHeader'.
exten => 1,1,PJSIP_HEADER(remove,X-MyHeader)
;
; Remove all headers that begin with 'X-My'.
exten => 1,1,PJSIP_HEADER(remove,X-My*)
;
; Remove all previously added headers.
exten => 1,1,PJSIP_HEADER(remove,*)
;
NOTE: If you call PJSIP_HEADER in a normal dialplan context, you'll be
operating on the *calling* channel which may not be what you want.  To operate
on the *called* channel (to set headers on the outgoing channel for instance),
call PJSIP_HEADER in a pre-dial handler. 
Example:
;
[handler]
exten => addheader,1,Set(PJSIP_HEADER(add,X-MyHeader)=myvalue)
exten => addheader,2,Set(PJSIP_HEADER(add,X-MyHeader2)=myvalue2)
;
[somecontext]
exten => 1,1,Dial(PJSIP/${EXTEN},,b(handler^addheader^1))
;

[Syntax]
PJSIP_HEADER(action,name[,number])

[Arguments]
action
    read - Returns instance <number> of the header named <name>.
    add - Adds a new header named <name> to this session.
    update - Updates instance <number> of the header named <name> to
    a new value.  The header must already exist.
    remove - Removes all instances of previously added headers whose
    names match <name>. A '*' may be appended to <name> to remove all headers
    *beginning with* <name>. A single '*' may be provided for <name> to clear
    *all* previously added headers. 
name
    The name of the header.
number
    If not specified, defaults to '1' meaning the first matching
    header.

[See Also]
</pre>
  </td>
 </tr>
</table>





<div style="margin-top: 1.5em;">
 <b style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Bugs: </b>


 <a href="https://issues.asterisk.org/jira/browse/ASTERISK-22498">ASTERISK-22498</a>


</div>



<div style="margin-top: 1.5em;">
 <b style="color: #575012; font-size: 10pt;">Repository: </b>
Asterisk
</div>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Description </h1>
 <table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">For PJSIP_HEADER, an incoming supplemental session callback is registered that takes the pjsip_hdrs from the incoming session and stores them in a linked list in the session datastore.  Calls to PJSIP_HEADER traverse over the list and return the nth matching header where 'n' is the 'number' argument to the function.

For PJSIPAddHeader, the first call creates a datastore and linked list and adds the datastore to the session.  The header is then created as a pjsip_hdr and added to the list.  An outgoing supplemental session callback then traverses the list and adds the headers to the outgoing pjsip_msg.

For PJSIPRemoveHeader, the list created with PJSIPAddHeader is traversed and all matching entries are removed.  As with SIPRemoveHeader, an empty arguments removes all headers previously added.

Rather than cloning the incoming pjsip_msg or using pjsip_msg to accumulate the outgoing headers, I used a simple AST_LIST. There was a lot of overhead with the clone functions and some tricky behavior with the pjsip_msg/pjsip_hdr internal lists. Using the AST_LISTs cut down on both instructions and memory.  

All memory allocation is from the pj_pool attached to the session.</pre>
  </td>
 </tr>
</table>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Testing </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Tested successfully...
PJSIP_HEADER return the full value of nth specified header from either the incoming session, or headers previously added to the outgoing session by PJSIPHeader.
PJSIP_HEADER fails if there was no header specified in the function call.
PJSIP_HEADER fails if there was no datastore on the incoming session (should never happen).
PJSIP_HEADER fails if the nth header wasn't found.

PJSIPAddHeader adds a pjsip_hdr structure to the linked list when the input string is properly formatted as "header_name:\s*header_value".
PJSIPAddHeader fails if no ':' was found in the input string.
PJSIPAddHeader fails if after parsing either the header name or value is empty.

PJSIPRemoveHeader removes all matching headers from the linked list when a partial header name is specified.
PJSIPRemoveHeader removes all matching headers from the linked list when a full header is specified with a trailing ':'.
PJSIPRemoveHeader removes all previously added header from the linked list when no header is specified.
PJSIPRemoveHeader returns successfully (silently) if there was no linked list.


</pre>
  </td>
 </tr>
</table>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Diffs</b> (updated)</h1>
<ul style="margin-left: 3em; padding-left: 0;">

 <li>/branches/12/res/res_pjsip_header_funcs.c <span style="color: grey">(PRE-CREATION)</span></li>

</ul>

<p><a href="https://reviewboard.asterisk.org/r/2858/diff/" style="margin-left: 3em;">View Diff</a></p>







  </td>
 </tr>
</table>




  </div>
 </body>
</html>