컴퓨터이야기/C

oSIP 라이브러리.

백구씨쥔장 2008. 1. 15. 18:02

RFC 3261.
17장의 Transaction 부분, 4개의 transaction.
- INVITE CLIENT TRANSACTION
- NON-INVITE CLIENT TRANSACTION
- INVITE SERVER TRANSACTION
- NON-INVITE SERVER TRANSACTION

T1, default 500ms
exponential backoff


 /**
 * Enumeration for transaction type.
 * A transaction can be either of:
 *  ICT,
 *  IST,
 *  NICT,
 *  NIST,
 */
  typedef enum osip_fsm_type_t
  {
    ICT, /**< Invite Client (outgoing) Transaction */
    IST, /**< Invite Server (incoming) Transaction */
    NICT,/**< Non-Invite Client (outgoing) Transaction */
    NIST /**< Non-Invite Server (incoming) Transaction */
  }
  osip_fsm_type_t;
 

  typedef struct osip_transaction osip_transaction_t;
  struct osip_transaction
  {

    void *your_instance;        /**< User Defined Pointer. */
    int transactionid;          /**< Internal Transaction Identifier. */
    osip_fifo_t *transactionff; /**< events must be added in this fifo */

    osip_via_t *topvia;         /**< CALL-LEG definition (Top Via) */
    osip_from_t *from;          /**< CALL-LEG definition (From)    */
    osip_to_t *to;              /**< CALL-LEG definition (To)      */
    osip_call_id_t *callid;     /**< CALL-LEG definition (Call-ID) */
    osip_cseq_t *cseq;          /**< CALL-LEG definition (CSeq)    */

    osip_message_t *orig_request;  /**< Initial request            */
    osip_message_t *last_response; /**< Last response              */
    osip_message_t *ack;           /**< ack request sent           */

    state_t state;              /**< Current state of the transaction */

    time_t birth_time;          /**< birth date of transaction        */
    time_t completed_time;      /**< end   date of transaction        */

    int in_socket;              /**< Optional socket for incoming message */
    int out_socket;             /**< Optional place for outgoing message */

    void *config;               /**@internal transaction is managed by osip_t  */

    osip_fsm_type_t ctx_type;   /**< Type of the transaction */
    osip_ict_t *ict_context;    /**@internal */
    osip_ist_t *ist_context;    /**@internal */
    osip_nict_t *nict_context;  /**@internal */
    osip_nist_t *nist_context;  /**@internal */
    osip_srv_record_t record;   /**@internal */
  };

  typedef struct osip osip_t;
  struct osip
  {
    void *application_context;  /**< User defined Pointer */

    /* list of transactions for ict, ist, nict, nist */
    osip_list_t osip_ict_transactions;   /**< list of ict transactions */
    osip_list_t osip_ist_transactions;   /**< list of ist transactions */
    osip_list_t osip_nict_transactions;  /**< list of nict transactions */
    osip_list_t osip_nist_transactions;  /**< list of nist transactions */

    osip_list_t ixt_retransmissions;    /**< list of ixt elements */

    osip_message_cb_t msg_callbacks[OSIP_MESSAGE_CALLBACK_COUNT];        /**@internal */
    osip_kill_transaction_cb_t kill_callbacks[OSIP_KILL_CALLBACK_COUNT]; /**@internal */
    osip_transport_error_cb_t tp_error_callbacks OSIP_TRANSPORT_ERROR_CALLBACK_COUNT];
    int (*cb_send_message) (osip_transaction_t *, osip_message_t *, char *,  int, int);  /**@internal */
  };

######
######
17 Transactions

   SIP is a transactional protocol: interactions between components take place in a series of independent message exchanges.  Specifically, a SIP transaction consists of a single request and any responses to
that request, which include zero or more provisional responses and one or more final responses.  In the case of a transaction where the request was an INVITE (known as an INVITE transaction), the
   transaction also includes the ACK only if the final response was not
   a 2xx response.  If the response was a 2xx, the ACK is not considered
   part of the transaction.

      The reason for this separation is rooted in the importance of delivering all 200 (OK) responses to an INVITE to the UAC.  To deliver them all to the UAC, the UAS alone takes responsibility  for retransmitting them (see Section 13.3.1.4), and the UAC alone takes responsibility for acknowledging them with ACK (see Section13.2.2.4).  Since this ACK is retransmitted only by the UAC, it is effectively considered its own transaction.

   Transactions have a client side and a server side.  The client side is known as a client transaction and the server side as a server transaction.  The client transaction sends the request, and the server transaction sends the response.  The client and server transactions are logical functions that are embedded in any number of elements.  Specifically, they exist within user agents and stateful
   proxy servers.  Consider the example in Section 4.  In this example, the UAC executes the client transaction, and its outbound proxy executes the server transaction.  The outbound proxy also executes a
   client transaction, which sends the request to a server transaction in the inbound proxy.  That proxy also executes a client transaction, which in turn sends the request to a server transaction in the UAS.
   This is shown in Figure 4.

   +---------+        +---------+        +---------+        +---------+
   |      +-+|Request |+-+   +-+|Request |+-+   +-+|Request |+-+      |
   |      |C||------->||S|   |C||------->||S|   |C||------->||S|      |
   |      |l||        ||e|   |l||        ||e|   |l||        ||e|      |
   |      |i||        ||r|   |i||        ||r|   |i||        ||r|      |
   |      |e||        ||v|   |e||        ||v|   |e||        ||v|      |
   |      |n||        ||e|   |n||        ||e|   |n||        ||e|      |
   |      |t||        ||r|   |t||        ||r|   |t||        ||r|      |
   |      | ||        || |   | ||        || |   | ||        || |      |
   |      |T||        ||T|   |T||        ||T|   |T||        ||T|      |
   |      |r||        ||r|   |r||        ||r|   |r||        ||r|      |
   |      |a||        ||a|   |a||        ||a|   |a||        ||a|      |
   |      |n||        ||n|   |n||        ||n|   |n||        ||n|      |
   |      |s||Response||s|   |s||Response||s|   |s||Response||s|      |
   |      +-+|<-------|+-+   +-+|<-------|+-+   +-+|<-------|+-+      |
   +---------+        +---------+        +---------+        +---------+
      UAC               Outbound           Inbound              UAS
                        Proxy               Proxy

                  Figure 4: Transaction relationships

   A stateless proxy does not contain a client or server transaction.
   The transaction exists between the UA or stateful proxy on one side,and the UA or stateful proxy on the other side.  As far as SIP transactions are concerned, stateless proxies are effectively transparent.  The purpose of the client transaction is to receive a request from the element in which the client is embedded (call this element the "Transaction User" or TU; it can be a UA or a stateful proxy), and reliably deliver the request to a server transaction.

   The client transaction is also responsible for receiving responses and delivering them to the TU, filtering out any response retransmissions or disallowed responses (such as a response to ACK).
   Additionally, in the case of an INVITE request, the client transaction is responsible for generating the ACK request for any final response accepting a 2xx response.

   Similarly, the purpose of the server transaction is to receive requests from the transport layer and deliver them to the TU.  The server transaction filters any request retransmissions from the network.  The server transaction accepts responses from the TU and delivers them to the transport layer for transmission over the
   network.  In the case of an INVITE transaction, it absorbs the ACK request for any final response excepting a 2xx response.

   The 2xx response and its ACK receive special treatment.  This response is retransmitted only by a UAS, and its ACK generated only by the UAC.  This end-to-end treatment is needed so that a caller
   knows the entire set of users that have accepted the call.  Because of this special handling, retransmissions of the 2xx response are handled by the UA core, not the transaction layer.  Similarly,
   generation of the ACK for the 2xx is handled by the UA core.  Each proxy along the path merely forwards each 2xx response to INVITE and its corresponding ACK.

17.1 Client Transaction

   The client transaction provides its functionality through the maintenance of a state machine.

   The TU communicates with the client transaction through a simple interface.  When the TU wishes to initiate a new transaction, it creates a client transaction and passes it the SIP request to send
   and an IP address, port, and transport to which to send it.  The client transaction begins execution of its state machine.  Valid responses are passed up to the TU from the client transaction.

   There are two types of client transaction state machines, depending on the method of the request passed by the TU.  One handles client transactions for INVITE requests.  This type of machine is referred
   to as an INVITE client transaction.  Another type handles client transactions for all requests except INVITE and ACK.  This is referred to as a non-INVITE client transaction.  There is no client transaction for ACK.  If the TU wishes to send an ACK, it passes one  directly to the transport layer for transmission.

   The INVITE transaction is different from those of other methods because of its extended duration.  Normally, human input is required  in order to respond to an INVITE.  The long delays expected for
   sending a response argue for a three-way handshake.  On the other hand, requests of other methods are expected to complete rapidly.
   Because of the non-INVITE transaction's reliance on a two-way  handshake, TUs SHOULD respond immediately to non-INVITE requests.

17.1.1 INVITE Client Transaction

17.1.1.1 Overview of INVITE Transaction

   The INVITE transaction consists of a three-way handshake.  The client transaction sends an INVITE, the server transaction sends responses, and the client transaction sends an ACK.  For unreliable transports
   (such as UDP), the client transaction retransmits requests at an interval that starts at T1 seconds and doubles after every retransmission.  T1 is an estimate of the round-trip time (RTT), and it defaults to 500 ms.  Nearly all of the transaction timers described here scale with T1, and changing T1 adjusts their values.
   The request is not retransmitted over reliable transports.  After receiving a 1xx response, any retransmissions cease altogether, and the client waits for further responses.  The server transaction can
   send additional 1xx responses, which are not transmitted reliably by the server transaction.  Eventually, the server transaction decides to send a final response.  For unreliable transports, that response
   is retransmitted periodically, and for reliable transports, it is sent once.  For each final response that is received at the client transaction, the client transaction sends an ACK, the purpose of which is to quench retransmissions of the response.

17.1.1.2 Formal Description

   The state machine for the INVITE client transaction is shown in Figure 5.  The initial state, "calling", MUST be entered when the TU initiates a new client transaction with an INVITE request.  The client transaction MUST pass the request to the transport layer for transmission (see Section 18).  If an unreliable transport is being used, the client transaction MUST start timer A with a value of T1.
   If a reliable transport is being used, the client transaction SHOULD NOT start timer A (Timer A controls request retransmissions).  For any transport, the client transaction MUST start timer B with a value
   of 64*T1 seconds (Timer B controls transaction timeouts).

   When timer A fires, the client transaction MUST retransmit the request by passing it to the transport layer, and MUST reset the timer with a value of 2*T1.  The formal definition of retransmit within the context of the transaction layer is to take the message previously sent to the transport layer and pass it to the transport
   layer once more.

   When timer A fires 2*T1 seconds later, the request MUST be retransmitted again (assuming the client transaction is still in this state).  This process MUST continue so that the request is retransmitted with intervals that double after each transmission.
   These retransmissions SHOULD only be done while the client transaction is in the "calling" state.

   The default value for T1 is 500 ms.  T1 is an estimate of the RTT between the client and server transactions.  Elements MAY (though it is NOT RECOMMENDED) use smaller values of T1 within closed, private networks that do not permit general Internet connection.  T1 MAY be chosen larger, and this is RECOMMENDED if it is known in advance  (such as on high latency access links) that the RTT is larger.
   Whatever the value of T1, the exponential backoffs on retransmissions described in this section MUST be used.

   If the client transaction is still in the "Calling" state when timer  B fires, the client transaction SHOULD inform the TU that a timeout has occurred.  The client transaction MUST NOT generate an ACK.  The
   value of 64*T1 is equal to the amount of time required to send seven requests in the case of an unreliable transport.

   If the client transaction receives a provisional response while in  the "Calling" state, it transitions to the "Proceeding" state. In the "Proceeding" state, the client transaction SHOULD NOT retransmit the
   request any longer. Furthermore, the provisional response MUST be passed to the TU.  Any further provisional responses MUST be passed up to the TU while in the "Proceeding" state.

   When in either the "Calling" or "Proceeding" states, reception of a response with status code from 300-699 MUST cause the client transaction to transition to "Completed".  The client transaction MUST pass the received response up to the TU, and the client transaction MUST generate an ACK request, even if the transport is reliable (guidelines for constructing the ACK from the response are given in Section 17.1.1.3) and then pass the ACK to the transport layer for transmission.  The ACK MUST be sent to the same address, port, and transport to which the original request was sent.  The client transaction SHOULD start timer D when it enters the "Completed" state, with a value of at least 32 seconds for unreliable transports, and a value of zero seconds for reliable transports.
   Timer D reflects the amount of time that the server transaction can remain in the "Completed" state when unreliable transports are used. This is equal to Timer H in the INVITE server transaction, whose

   default is 64*T1.  However, the client transaction does not know the value of T1 in use by the server transaction, so an absolute minimum of 32s is used instead of basing Timer D on T1.

   Any retransmissions of the final response that are received while in the "Completed" state MUST cause the ACK to be re-passed to the transport layer for retransmission, but the newly received response
   MUST NOT be passed up to the TU.  A retransmission of the response is defined as any response which would match the same client transaction based on the rules of Section 17.1.3.

                               |INVITE from TU
             Timer A fires     |INVITE sent
             Reset A,          V                      Timer B fires
             INVITE sent +-----------+                or Transport Err.
               +---------|           |---------------+inform TU
               |         |  Calling  |               |
               +-------->|           |-------------->|
                         +-----------+ 2xx           |
                            |  |       2xx to TU     |
                            |  |1xx                  |
    300-699 +---------------+  |1xx to TU            |
   ACK sent |                  |                     |
resp. to TU |  1xx             V                     |
            |  1xx to TU  -----------+               |
            |  +---------|           |               |
            |  |         |Proceeding |-------------->|
            |  +-------->|           | 2xx           |
            |            +-----------+ 2xx to TU     |
            |       300-699    |                     |
            |       ACK sent,  |                     |
            |       resp. to TU|                     |
            |                  |                     |      NOTE:
            |  300-699         V                     |
            |  ACK sent  +-----------+Transport Err. |  transitions
            |  +---------|           |Inform TU      |  labeled with
            |  |         | Completed |-------------->|  the event
            |  +-------->|           |               |  over the action
            |            +-----------+               |  to take
            |              ^   |                     |
            |              |   | Timer D fires       |
            +--------------+   | -                   |
                               |                     |
                               V                     |
                         +-----------+               |
                         |           |               |
                         | Terminated|<--------------+
                         |           |
                         +-----------+

                 Figure 5: INVITE client transaction

   If timer D fires while the client transaction is in the "Completed" state, the client transaction MUST move to the terminated state.

   When in either the "Calling" or "Proceeding" states, reception of a 2xx response MUST cause the client transaction to enter the "Terminated" state, and the response MUST be passed up to the TU.
   The handling of this response depends on whether the TU is a proxy core or a UAC core.  A UAC core will handle generation of the ACK for this response, while a proxy core will always forward the 200 (OK)
   upstream.  The differing treatment of 200 (OK) between proxy and UAC is the reason that handling of it does not take place in the transaction layer.

   The client transaction MUST be destroyed the instant it enters the "Terminated" state.  This is actually necessary to guarantee correct operation.  The reason is that 2xx responses to an INVITE are treated
   differently; each one is forwarded by proxies, and the ACK handling in a UAC is different.  Thus, each 2xx needs to be passed to a proxy core (so that it can be forwarded) and to a UAC core (so it can be
   acknowledged).  No transaction layer processing takes place.
   Whenever a response is received by the transport, if the transport layer finds no matching client transaction (using the rules of Section 17.1.3), the response is passed directly to the core.  Since the matching client transaction is destroyed by the first 2xx, subsequent 2xx will find no match and therefore be passed to the core.


마지막 문장이 잘 이해가 아니감. -_-;;;