Changes between Initial Version and Version 1 of SIP_Message_Buffer_Event


Ignore:
Timestamp:
Jan 17, 2008 8:53:40 AM (17 years ago)
Author:
bennylp
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SIP_Message_Buffer_Event

    v1 v1  
     1= Message, Buffers, and Event = 
     2 
     3SIP message (request or response) is represented by [http://www.pjsip.org/pjsip/docs/html/structpjsip__msg.htm pjsip_msg] structure, but application would rarely see this structure passed directly in the API. For incoming and outgoing messages, the message would be contained in a RX or TX data buffer, [http://www.pjsip.org/pjsip/docs/html/structpjsip__rx__data.htm pjsip_rx_data] and [http://www.pjsip.org/pjsip/docs/html/structpjsip__tx__data.htm pjsip_tx_data] respectively. When passing SIP messages among modules, PJSIP also normally does not pass the buffers directly, but rather encapsulate it as [http://www.pjsip.org/pjsip/docs/html/structpjsip__event.htm pjsip_event] structure.  
     4 
     5The [http://www.pjsip.org/pjsip/docs/html/structpjsip__event.htm pjsip_event] is PJSIP's way to represent any known SIP event types, such as: 
     6 - arrival of SIP message 
     7 - transmission of SIP message 
     8 - transaction timeout event 
     9 - transport error 
     10 - and so on 
     11 
     12For detailed information about SIP messaging and RX/TX buffer design in PJSIP, please read the PJSIP Developer's Guide PDF in [http://www.pjsip.org/docs.htm PJSIP Documentation] page. 
     13 
     14---- 
     15 
     16= pjsip_event = 
     17 
     18pjsip_event structure mainly consists of two main member: 
     19 - {{{pjsip_event.type}}} shows the [http://www.pjsip.org/pjsip/docs/html/group__PJSIP__EVENT.htm#g887dd71c4680ebf9f85ec69fd87b8399 event type] 
     20 - {{{pjsip_event.body}}} contains the data describing the event. This member is a C union, and which data to be extracted from the union depends on the event type. 
     21 
     22== pjsip_event Structure == 
     23 
     24{{{ 
     25typedef enum pjsip_event_id_e 
     26{ 
     27    PJSIP_EVENT_UNKNOWN,         /** Unidentified event. */ 
     28    PJSIP_EVENT_TIMER,           /** Timer event, normally only used internally in transaction. */ 
     29    PJSIP_EVENT_TX_MSG,          /** Message transmission event. */ 
     30    PJSIP_EVENT_RX_MSG,          /** Message received event. */ 
     31    PJSIP_EVENT_TRANSPORT_ERROR, /** Transport error event. */ 
     32    PJSIP_EVENT_TSX_STATE,       /** Transaction state changed event. */ 
     33    PJSIP_EVENT_USER             /** Indicates that the event was triggered by user action. */ 
     34} pjsip_event_id_e; 
     35 
     36 
     37struct pjsip_event 
     38{ 
     39    /** This is necessary so that we can put events as a list. */ 
     40    PJ_DECL_LIST_MEMBER(struct pjsip_event); 
     41 
     42    /** The event type */ 
     43    pjsip_event_id_e type; 
     44 
     45    /** The event body as union, which fields depends on the event type. */ 
     46    union { 
     47        /** Timer event. */ 
     48        struct { 
     49            pj_timer_entry *entry;      /**< The timer entry.           */ 
     50        } timer; 
     51 
     52        /** Transaction state has changed event. */ 
     53        struct { 
     54            union { 
     55                pjsip_rx_data   *rdata; /**< The incoming message.      */ 
     56                pjsip_tx_data   *tdata; /**< The outgoing message.      */ 
     57                pj_timer_entry  *timer; /**< The timer.                 */ 
     58                pj_status_t      status;/**< Transport error status.    */ 
     59                void            *data;  /**< Generic data.              */ 
     60            } src; 
     61            pjsip_transaction   *tsx;   /**< The transaction.           */ 
     62            int                  prev_state; /**< Previous state.       */ 
     63            pjsip_event_id_e     type;  /**< Type of event source:      */ 
     64        } tsx_state; 
     65 
     66        /** Message transmission event. */ 
     67        struct { 
     68            pjsip_tx_data       *tdata; /**< The transmit data buffer.  */ 
     69        } tx_msg; 
     70 
     71        /** Transmission error event. */ 
     72        struct { 
     73            pjsip_tx_data       *tdata; /**< The transmit data.         */ 
     74            pjsip_transaction   *tsx;   /**< The transaction.           */ 
     75        } tx_error; 
     76 
     77        /** Message arrival event. */ 
     78        struct { 
     79            pjsip_rx_data       *rdata; /**< The receive data buffer.   */ 
     80        } rx_msg; 
     81 
     82        /** User event. */ 
     83        struct { 
     84            void                *user1; /**< User data 1.               */ 
     85            void                *user2; /**< User data 2.               */ 
     86            void                *user3; /**< User data 3.               */ 
     87            void                *user4; /**< User data 4.               */ 
     88        } user; 
     89 
     90    } body; 
     91}; 
     92}}} 
     93 
     94 
     95== Events == 
     96 
     97This section describes various event types and what relevant data can be extracted from the event. 
     98 
     99=== Timer Event === 
     100 
     101||Type: || PJSIP_EVENT_TIMER || 
     102||Data: || event.body.'''timer''' contains the timer entry || 
     103||Description: || The timer event is emitted when a scheduled timer has elapsed. It is only used internally in transaction layer, and it will never reach application  
     104|| 
     105 
     106=== RX Message Event === 
     107 
     108||Type: || PJSIP_EVENT_RX_MSG || 
     109||Data: || event.body.'''rx_msg''' contains [http://www.pjsip.org/pjsip/docs/html/structpjsip__rx__data.htm pjsip_rx_data] || 
     110||Description: || The RX message event is emitted by the transport layer upon arrival of a packet and after the packet is parsed successfully. The transport layer then hand over this event to pjsip_endpoint which will distribute this event to all registered modules. An application (which is a module in PJSIP) only receives this event for SIP messages that are '''outside''' any transactions. For SIP messages belonging to a transaction, the transaction layer would have filtered this event (thus it will not reach dialog or application layer), and the event will be forwarded to upper layer as ''Transaction State Progression'' event instead (see below). 
     111|| 
     112 
     113=== TX Message Event === 
     114 
     115||Type: || PJSIP_EVENT_TX_MSG || 
     116||Data: || event.body.'''tx_msg''' contains [http://www.pjsip.org/pjsip/docs/html/structpjsip__tx__data.htm pjsip_tx_data] || 
     117||Description: || This event represents transmission of outgoing message. 
     118|| 
     119 
     120=== Transmission Error Event === 
     121 
     122||Type: || PJSIP_EVENT_TRANSPORT_ERROR || 
     123||Data: || event.body.'''tx_error''' contains the pjsip_tx_data that failed to be sent and optionally the transaction that sent the message || 
     124||Description: || This event is only used internally in PJSIP, and it will never reach application. 
     125|| 
     126 
     127=== Transaction State Progression Event === 
     128 
     129||Type: || PJSIP_EVENT_TSX_STATE || 
     130||Data: || event.body.'''tsx_state''' contains description about the state progression (see below) || 
     131||Description: || This event is emitted by SIP transaction to notify the transaction user that the transaction state has changed. If the transaction user is a dialog, the dialog will also notify the dialog usages (such as invite session or presence subscription), and the dialog usage may further notify the application about the state change. || 
     132 
     133This event is the most common event seen by application. Various callbacks in PJSIP that emit this event: 
     134 - In PJSUA-API: ''on_call_state()'' and ''on_call_tsx_state()'' callbacks 
     135 - In invite session layer: ''on_state_changed()'', ''on_new_session()'', and ''on_tsx_state_changed()'' 
     136 - In SIMPLE/presence layer: ''on_evsub_state()'' and ''on_tsx_state()'' callbacks 
     137 
     138The event.body.'''tsx_state''' contains these fields: 
     139 - '''tsx''': the transaction which state has changed 
     140 - '''prev_state''': the previous transaction state 
     141 - '''type''': the type of event that caused the transaction state to change (arrival of message, timeout event, etc.) 
     142 - '''src''': a union containing further data associated with the event that caused the transaction state change.  
     143 
     144Application can inspect the original event that caused the transaction state to change by inspecting the '''type''' and '''src''' fields as described above. The relationship between '''type''' and '''src''' fields are as follows. 
     145 
     146Incoming message:: 
     147 If transaction changed state because of incoming message: 
     148   - ''type'': PJSIP_EVENT_RX_MSG 
     149   - ''src'': ''src.rdata'' contains [http://www.pjsip.org/pjsip/docs/html/structpjsip__rx__data.htm pjsip_rx_data] 
     150 
     151Outgoing transmission:: 
     152 If transaction changed state because of outgoing transmission: 
     153   - ''type'': PJSIP_EVENT_TX_MSG 
     154   - ''src'': ''src.tdata'' contains [http://www.pjsip.org/pjsip/docs/html/structpjsip__tx__data.htm pjsip_tx_data] 
     155 
     156Timer event:: 
     157 If transaction changed state because of (timeout) timer event: 
     158   - ''type'': PJSIP_EVENT_TIMER 
     159   - ''src'': ''src.timer'' contains the timer entry 
     160 
     161Transport error:: 
     162 If transaction changed state because of transport error: 
     163   - ''type'': PJSIP_EVENT_TRANSPORT_ERROR 
     164   - ''src'': ''src.status'' contains the transport error status 
     165 
     166 
     167=== User Event === 
     168 
     169||Type: || PJSIP_EVENT_USER || 
     170||Data: || event.body.'''user''' contains user data || 
     171||Description: || Currently this is not used || 
     172 
     173 
     174---- 
     175 
     176= Getting the SIP Message from pjsip_event = 
     177 
     178Before we can get the SIP message, first we need to get the [http://www.pjsip.org/pjsip/docs/html/structpjsip__rx__data.htm pjsip_rx_data] or [http://www.pjsip.org/pjsip/docs/html/structpjsip__tx__data.htm pjsip_tx_data], depending on whether the event is related to receipt or transmission of SIP message. 
     179 
     180== Retrieving SIP Message from an Incoming Message == 
     181 
     182First we need to extract [http://www.pjsip.org/pjsip/docs/html/structpjsip__rx__data.htm pjsip_rx_data] from the event: 
     183 
     184{{{ 
     185static pjsip_rx_data *get_rx_data(pjsip_event *e) 
     186{ 
     187   if (e->type == PJSIP_EVENT_RX_MSG) 
     188      return e->body.rx_msg.rdata; 
     189 
     190   if (e->type == PJSIP_EVENT_TSX_STATE && e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) 
     191      return e->body.tsx_state.src.rdata; 
     192    
     193   // There's no rdata on this eevnt 
     194   return NULL; 
     195} 
     196}}} 
     197 
     198Once we get the [http://www.pjsip.org/pjsip/docs/html/structpjsip__rx__data.htm pjsip_rx_data], we can extract the SIP message: 
     199 
     200{{{ 
     201   pjsip_msg *msg = rdata->msg_info.msg; 
     202}}} 
     203 
     204 
     205== Retrieving SIP Message from an Outgoing Message == 
     206 
     207First we need to extract [http://www.pjsip.org/pjsip/docs/html/structpjsip__tx__data.htm pjsip_tx_data] from the arbitrary event: 
     208 
     209{{{ 
     210static pjsip_rx_data *get_tx_data(pjsip_event *e) 
     211{ 
     212   if (e->type == PJSIP_EVENT_TX_MSG) 
     213      return e->body.tx_msg.tdata; 
     214 
     215   if (e->type == PJSIP_EVENT_TSX_STATE && e->body.tsx_state.type == PJSIP_EVENT_TX_MSG) 
     216      return e->body.tsx_state.src.tdata; 
     217    
     218   // There's no tdata on this eevnt 
     219   return NULL; 
     220} 
     221}}} 
     222 
     223Once we get the [http://www.pjsip.org/pjsip/docs/html/structpjsip__tx__data.htm pjsip_tx_data], we can extract the SIP message: 
     224 
     225{{{ 
     226   pjsip_msg *msg = tdata->msg; 
     227}}} 
     228 
     229---- 
     230 
     231= Manipulating the SIP Message = 
     232 
     233Below are few snippets on how to manipulate SIP messages. Please see [http://www.pjsip.org/pjsip/docs/html/group__PJSIP__MSG.htm SIP Messaging Elements] in [http://www.pjsip.org/pjsip/docs/html/index.htm PJSIP documentation] for the complete documentation. 
     234 
     235== Processing Request Line == 
     236 
     237{{{ 
     238  if (msg->type == PJSIP_REQUEST_MSG) { 
     239     pjsip_method *m = &msg->line.req.method; 
     240     pjsip_uri *uri = msg->line.req.uri; 
     241  } 
     242}}} 
     243 
     244== Processing Status Line == 
     245 
     246{{{ 
     247  if (msg->type == PJSIP_RESPONSE_MSG) { 
     248     int code = msg->line.status.code; 
     249     pj_str_t reason = msg->line.status.reason; 
     250  } 
     251}}} 
     252 
     253== Finding a Particular Header == 
     254 
     255To find header by its type: 
     256 
     257{{{ 
     258  pjsip_contact_hdr *h = (pjsip_contact_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL); 
     259}}} 
     260 
     261or to find header by its name: 
     262 
     263{{{ 
     264  const pj_str_t hname = pj_str("Contact"); 
     265  pjsip_contact_hdr *h = (pjsip_contact_hdr*) pjsip_msg_find_hdr_by_name(msg, &hname, NULL); 
     266}}} 
     267 
     268== Finding Multiple Headers == 
     269 
     270To find all Contact headers: 
     271 
     272{{{ 
     273  pjsip_hdr *h; 
     274   
     275  h = msg->hdr.next; 
     276  while (h != &msg->hdr) { 
     277     if (h->type == PJSIP_H_CONTACT) { 
     278        // h is Contact hdr, do something with it .. 
     279        pjsip_contact_hdr *hc = (pjsip_contact_hdr*)h; 
     280        ... 
     281     } 
     282     h = h->next; 
     283  } 
     284}}} 
     285 
     286or 
     287 
     288{{{ 
     289  pjsip_hdr *h; 
     290 
     291  h = pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL); 
     292  while (h != NULL) { 
     293    // h is Contact hdr, do something with it .. 
     294    pjsip_contact_hdr *hc = (pjsip_contact_hdr*)h; 
     295    ... 
     296 
     297    // find next Contact header after h, only if h is not the last header 
     298    if (h->next == &msg->hdr) 
     299       break; 
     300    h = pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, h->next); 
     301  } 
     302}}} 
     303 
     304 
     305== Adding a Header == 
     306 
     307{{{ 
     308  pjsip_hdr *hdr = .. your header .. 
     309 
     310  // To add hdr as the last header in msg: 
     311  pjsip_msg_add_hdr(msg, hdr); 
     312   
     313  // To add hdr as the first header in msg 
     314  //   pjsip_msg_insert_first_hdr(msg, hdr) 
     315 
     316  // To add hdr after some header (for example after Content-Type) 
     317  //   pjsip_hdr *hctype = pjsip_msg_find_hdr(msg, PJSIP_H_CONTENT_TYPE, NULL); 
     318  //   if (hctype) 
     319  //        pj_list_insert_after(hctype, hdr); 
     320 
     321}}}