HP-UX C SIP Stack Programmer’s Guide HP-UX 11i v2 Version 4.5 Manufacturing Part Number: 5992-3333 November 2007 © Copyright 2007 Hewlett-Packard Development Company, L.P.
Legal Notices © Copyright 2007 Hewlett-Packard Development Company, L.P. Confidential computer software. Valid license from HP required for possession, use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer Software, Computer Software Documentation and Technical Data for Commercial Items are licensed to the U.S. Government under vendor’s standard commercial license. The information contained herein is subject to change without notice.
CONTENTS 1 Session Initiation Protocol (SIP) Introduction 1 SIP Entities User Agent Proxy Server Redirect Server Registrar B2BUA 1 2 2 2 2 2 Messages Message Types Message Parts Message Samples 2 2 5 6 Entity Interaction Session Establishment and Termination Call Redirection Call Proxying 2 9 9 10 12 SIP Stack Introduction 15 TOOLKIT COMPONENTS 15 SIP Stack Architecture Stack Manager Layer User Agent layer Transaction Layer Transport Layer Message Layer 17 17 17 18 18 18 SIP Stack Objects
Stack Object Dialog (Call-leg) Register-Client Transaction Subscription Notification iv 19 19 19 20 20 20 Application Programming Interface (API) API Modules 20 20 Conformance to Standards SIP Stack Methods Responses New Message Parameters Security Multipart MIME Bodies Advanced DNS Queries 22 22 23 23 23 23 23 23 Feature Support SUBSCRIBE-NOTIFY (SIP Events) REFER SIP-T PRACK ENUM Connection Reuse Parsing TEL, PRES and IM URIs Service-route and Path Headers SIP Session Timer Replaces Header Extensib
Memory Requirements 3 4 5 API Conventions Introduction 29 Conventions Status Codes Types Function Parameters 29 29 31 31 Creating an Application Introduction 33 Initialization 33 Event Processing 35 Destruction 36 Configuration Resource Allocation Log Filters Network Configuration Timer Configuration Behavior Configuration Proxy Configuration Multithreaded Configuration 36 36 36 38 38 38 39 39 Getting Module Handles 39 SIP Stack Threading Model Multithreading Modes Multithreaded Mode Con
vi Call-leg 43 Call-leg Manager Working with Handles 43 43 Call-leg API Call-leg Parameters Call-leg Control Events 44 44 46 50 Call-leg State Machine Basic Call-leg States Advanced Call-leg States 52 52 56 Call-Leg Manager API Registering Application Callbacks Exchanging Handles with the Application 59 60 62 Initiating a Call 62 Making a TCP Call 63 Using the Outbound Message Mechanism 66 Call-leg re-INVITE Re-Invite Object Re-Invite Control Re-Invite Events 67 67 67 68 Call-leg re-INVIT
Call-leg Merging Functionality 7 8 89 Working with Transactions Introduction Transaction Entities Working with Handles 91 92 92 Transaction API Transaction Parameters Transaction Control Proxy Transaction Control Events 92 93 96 98 99 Transaction State Machine Client General Transaction Server General Transaction Client INVITE Transaction Server INVITE Transaction Client CANCEL Transaction Server CANCEL Transaction Transaction Advanced States 101 102 104 106 109 113 114 116 Transaction Manager API
Register-Client Control Events Register-Client State Machine Basic Register-Client States Advanced Register-Client States 9 viii 133 134 135 136 138 Register-Client Refresh Mechanism 140 Register-Client Manager API 140 Registering Application Callbacks 141 Exchanging Handles with the Application 143 Global Call-ID 143 Initiating a Register-Client 143 Working with SIP Messages Introduction 147 Working with Handles 148 Message Manager Object 148 Message Objects 149 Header Objects 150
10 Bad Syntax Parameter Bad Syntax Header Bad Syntax Start Line Handling Bad Syntax Messages Fixing Bad Syntax Messages Bad Syntax Events (Callbacks) Bad Syntax API 164 165 165 165 168 168 169 Working With Multipart MIME Message Multipart Body Structure Content-Type Header Headers in the Body Part object Parsing a Multipart Body Creating a Multipart Body Encoding a Multipart Body Body String 174 175 177 178 179 181 183 183 Authentication Introduction Shared Secret Digest Authentication with MD5 Authent
11 12 x Working with Transmitters Introduction Transmitter Entities 211 211 Working With Handles 212 Transmitter API Transmitter Parameters Transmitter Control Events 212 212 215 217 Transmitter State Machine 218 Sending Buffers with Transmitter Objects 222 Transmitter Manager API 223 Event Notification Introduction Definitions 229 229 Typical Message Flow 230 SIP Stack Event Notification Feature Subscription Entities 231 232 Working with Handles 233 Subscription Manager API Subscript
13 14 Sending a Notification 257 Out-of-Band Subscription Notifier Out-of-Band Subscription State Machine Subscriber Out-of-Band Subscription State Machine 259 260 261 Support for Subscription Forking Working with Subscription Forking Handling Multiple Notify Requests Subscription Forking Events Subscription Forking API Subscription Forking State Machine Subscription Forking Call Flow Subscription Forking Configuration 264 264 264 266 266 266 267 269 Authentication and DNS 269 REFER 269 REFER In
xii Application Connections Persistency Levels 287 287 Working with Connections Connections Transport Manager Working with Handles 293 293 293 293 Connection API Connection Parameters Connection Creation and Initialization Connection Control Functions Connection Events Connection States Client Connection State Machine 294 294 295 295 297 298 300 Server Connections Server Connection API Server Connection Events Server Connection States Server Connection State Machine Closing Server Connections 302 30
15 Working with IPv6 Addresses IPv6 Address Syntax Scope ID Compiling the SIP Stack with IPv6 IPv6 Addresses and SIP Initializing the SIP Stack with IPv6 IPv6 Addresses and the Transport Address Structure 325 325 326 326 326 326 Transport Layer Raw Buffer and Message Monitoring Raw Buffer Events 327 327 Working with DNS Introduction Configuring DNS Parameters DNS/SRV Tree DNS/ENUM Record 16 327 329 329 330 331 SIP Stack Implementation 331 State Machine and API Functions 334 Manipulating the DNS
Resolver API Resolver Control Resolver Callbacks Resolver Manager Functions 17 18 SIP Stack Log Introduction 349 Source Identifiers 350 Log File 350 Log Messages 350 Log Configuration 351 Message Structure 353 Controlling the Log 353 Compilation Log Control 355 Memory Pool Introduction 19 xiv 345 345 346 346 357 Definitions 357 API Functions 357 Using the Memory Pool Constructing and Destructing a Memory Pool Copying a Page into a Buffer Copying a Buffer to a Page 358 358 360 36
Subscription Layer 20 370 Replaces Header Sending a Message with Replaces Header Receiving an Invite Message with Replaces header 372 372 373 SIP Session Timer Configuration Parameters Timers Mode of Operation Call-leg Session Timer Parameters API Functions Control Functions Callbacks 376 376 377 377 377 378 380 380 General URI Scheme Support Other URI Extension Support TEL URI Extension Support 384 384 385 Type of Service (TOS) 385 Changing the Top Via Header of the Message 388 Timer Configura
Event Notification Configuration Multithreading Advanced Features Log Configuration 21 22 C SIP Stack Libraries Library structure header files 419 419 420 Sample Applications example 1 example 2 example 3 example 4 420 420 422 424 425 Working with the Mid-Layer Introduction Threading considerations 427 427 Mid-layer Management API Mid-layer Manager Handle Initializing, Constructing and Destructing of the Mid-layer 427 428 428 Mid-layer Timer API Threading Considerations Timer Handle Timer control
Index 439 xvii
xviii HP-UX C SIP Stack Programmer’s Guide
About This Document This document discusses the SIP protocol in brief and describes how to use SIP stack libraries for developing SIP applications. It describes how to create, compile, and run applications that use the C SIP APIs on systems running HPUX 11i v2. The document printing date and part number indicate the document’s current edition. The printing date will change when a new edition is printed. Minor changes may be made at reprint without changing the printing date.
xx Chapter 4 Creating An Application Describes the basic code necessary to write an application using SIP Stack. Chapter 5 Sip Threading Model Describes how SIP Stack can work in any of three threading modes; No-threads, Threadsafe, and Multithreaded. Chapter 6 Working With Call-legs (Dialogs) Describes how SIP Stack uses call-leg APIs between two User Agents. Chapter 7 Working With Transactions Describes how to use functions and function callbacks in a Transaction API of SIP Stack.
Chapter 15 Working With DNS Describes how to use DNS procedures to allow a client to resolve a SIP Stack Uniform Resource Identifier (URI) into the IP address, port, and transport protocol. Chapter 16 Working With Resolvers Describes how to use resolvers to produce data that is related to DNS. Chapter 17 SIP Stack Log Describes how to use the logging module that produces output for debugging, monitoring and tracking of the activity of applications built with the SIP Stack.
In command synopsis, a vertical bar separates mutually exclusive arguments. | mount [ suid | nosuid ] This symbol indicates that you hold down the first named key while pressing the key or mouse button that follows the plus. Ctrl+A Related Information Additional information about SIP Stack is available at: http://docs.hp.
1 SESSION INITIATION PROTOCOL (SIP) INTRODUCTION The Session Initiation Protocol (SIP) is a signaling protocol for initiating, managing and terminating voice and video sessions across packet networks. Borrowing from Internet protocols, such as HTTP and SMTP, SIP is textencoded and highly extensible. SIP can be extended to accommodate features and services such as call control services, mobility and interoperability with existing telephony systems.
Messages USER AGENT In SIP, a User Agent (UA) is the endpoint entity. User Agents initiate and terminate sessions by exchanging requests and responses. RFC 3261 defines the User Agent as an application, which contains both a User Agent client and User Agent server, as follows: User Agent Client (UAC)—a client application that initiates SIP requests. User Agent Server (UAS)—a server application that contacts the user when a SIP request is received and that returns a response on behalf of the user.
Messages Responses—sent from the server to the client. REQUESTS Table 1-1 RESPONSES Request Messages Method Description INVITE Initiates a call, changes call parameters (re-INVITE). ACK Confirms a final response for INVITE. BYE Terminates a call. CANCEL Cancels searches and “ringing”. OPTIONS Queries the capabilities of the other side. REGISTER Registers with the Location Service. INFO Sends mid-session information that does not modify the session state.
Messages 4xx = Client Error—the request contains bad syntax or cannot be fulfilled at this server. 5xx = Server Error—the server failed to fulfill an apparently valid request. 6xx = Global Failure—the request cannot be fulfilled at any server.
Messages MESSAGE PARTS Table 1-2 Response Codes (Continued) Number Meaning 603 Decline 604 Does not exist anywhere 606 Not acceptable SIP messages are composed of the following three parts: Start line Headers Message body START LINE Every SIP message begins with a Start Line. The Start Line conveys the message type (method type in requests, and response code in responses) and the protocol version.
Messages Possible body types include: Multipurpose Internet Mail Extensions (MIME) Others—to be defined in the IETF and in specific implementations MESSAGE SAMPLES The following samples show the message exchange between two User Agents for the purpose of setting up a voice call. SIP user alice@hp.com invites SIP user bob@acme.com to a call for the purpose of discussing lunch. Alice sends an INVITE request containing a body. Bob replies with a 200 OK response also containing a body.
Messages Table 1-3 Request Message Samples (Continued) Request Message Line Description (blank line) Blank line marks end of SIP headers and beginning of body. v=0 Version. o=Alice 53655765 2353687637 IN IP4 128.3.4.5 Owner/creator and session identifier, session version address type and address. s=Call from Alice. Session subject. c=IN IP4 alice_ws.hp.com Connection information.
Messages Table 1-4 8 Response Message Samples (Continued) Response Message line Description (blank line) Blank line marks end of SIP headers and beginning of the body. v=0 Version. o=Bob 4858949 4858949 IN IP4 192.1.2.3 Owner/creator and session identifier, session version address type and address. s=Lunch Session subject. c=IN IP4 machine1.acme.com Connection information. m=audio 5004 RTP/AVP 0 3 Description of media streams the receiver of the call is willing to accept.
Entity Interaction ENTITY INTERACTION This section describes the interaction between SIP entities in various common session initiation scenarios. SESSION ESTABLISHMENT AND TERMINATION Figure 1-1 shows the interaction between two user agents during trivial session establishment and termination.
Entity Interaction SESSION TERMINATION CALL REDIRECTION 6. Bob picks up the call and the UA2 sends a 200 (OK) message to the calling UA. This message also contains a packet describing the media capabilities of Bob’s terminal. 7. UA1 sends an ACK request to confirm the 200 (OK) response was received. The session termination call flow proceeds as follows: 1. The caller decides to end the call and “hangs-up”. This results in a BYE request being sent to UA2. 2.
Entity Interaction CALL FLOW 1. First a SIP INVITE message is sent to bob@acme.com, but finds the Redirect server sip.acme.com along the signaling path. 2. The Redirect server looks up Bob’s current location in a Location Service using a non-SIP protocol (for example, LDAP). 3. The Location Service returns Bob’s current location: SIP address 3573572@gw.telco.com. 4. The Redirect Server returns this information to the calling UA using a 302 (Moved Temporarily) response.
Entity Interaction CALL PROXYING Figure 1-3 shows call set-up between two User Agents with the assistance of an intermediate Proxy server. Location Service 4: bob@lab.acme.com 3: bob@acme.com ? 1: INVITE bob@acme.com 2: 100/Trying Proxy Server User Agent 1 5: INVITE bob@ lab.acme.com 6: 100/Trying 7: 180/Ringing 8: 180/Ringing User Agent 2 9: 200/OK 10: 200/OK sip.acme.com 11: ACK bob@lab.acme.com a.toon.com lab.acme.com Figure 1-3 Call Proxying Scenario CALL FLOW 12 1.
Entity Interaction 5. The Proxy server decides to Proxy the call and creates a new INVITE transaction based on the original INVITE message, but with the Request-URI in the start line changed to bob@lab.acme.com. The Proxy server sends this request to the UA2. 6. The UA2 responds first with a 100 (Trying). 7. The UA2 responds with a 180 (Ringing) response. 8. The Proxy server forwards the 180 (Ringing) response back to the UA1. 9.
Entity Interaction 14 HP-UX C SIP Stack Programmer’s Guide
2 SIP STACK INTRODUCTION This chapter describes the SIP Stack's architecture, the relationship between Stack objects, APIs, standards and different kinds of support, enhanced features and add-on module in SIP.
TOOLKIT COMPONENTS Application SIP Toolkit API API SIP Stack OS Abstraction Layer (Core) Network Figure 2-1 SIP Toolkit Components Note Note The SIP Toolkit is coded in ANSI C.
SIP Stack Architecture SIP STACK ARCHITECTURE The SIP Stack consists of five main layers. The Stack Manager, User Agent, Transaction Layer and Message Layer each export a dedicated API. Figure 2-2 shows the relationship between the various layers under the application.
SIP Stack Architecture TRANSACTION LAYER The Transaction layer creates and manages transaction objects. Each transaction is responsible for maintaining states, and sending and receiving messages and retransmissions using the Transport layer. The Transaction layer also maps incoming messages to transactions. TRANSPORT LAYER The Transport layer handles SIP networking I/O. This layer manages UDP sockets and TCP connections, as specified in RFC 3261, and sends and receives messages.
SIP Stack Objects SIP STACK OBJECTS This section describes the main objects that the SIP Stack uses. Figure 2-3 illustrates the ownership relationship between SIP Stack objects.
Application Programming Interface (API) TRANSACTION A SIP transaction involves all messages sent between a client and server for the purpose of completing one signaling action, such as call establishment and call termination. The call-leg to which each transaction belongs and an identifier field called “CSeq” (command sequence) uniquely identifies the transaction.
Application Programming Interface (API) Resource management Stack initialization and shutdown Logging HIGH-LEVEL API The High-level API includes: Dialog (Call-leg) API Register-Client API Authentication API Subscription API DIALOG (CALL-LEG) API The Dialog (Call-leg) API enables you to create calls, terminate calls, modify existing calls (re-INVITE), authenticate calls and more.
Conformance to Standards TRANSACTION API The Transaction API enables you to handle transactions that are not related to a call-leg, such as OPTIONS. Using the API, you can create new transactions, send outgoing requests, and respond to incoming requests. The Transaction API provides a set of callbacks and hooks that enables you to control some of the transaction behavior. You can use the Transaction API to implement SIP servers such as Registrars or Proxies.
Feature Support METHODS The SIP Stack supports baseline SIP methods, such as INVITE, ACK, BYE, CANCEL, OPTIONS and REGISTER. In addition, the SIP Stack supports extension methods, such as REFER, NOTIFY, SUBSCRIBE, PRACK, MESSAGE, UPDATE, INFO and others. RESPONSES The SIP Stack supports all response code classes (1xx to 6xx) specified in RFC 3261.
Feature Support REFER The SIP Stack allows the implementation of transfer services through the use of the REFER extension method, as defined in RFC 3515. This includes the usage of NOTIFY messages. REFER processing is fully controllable by the application via the Subscription API. SIP-T SIP-T (SIP for Telephony, RFC 3372) is an umbrella specification defining how to interwork SIP with PSTN (SS7/ISUP) networks.
Feature Support connection. This frequently causes a pair of SIP entities to use one connection for requests sent in each direction, and can result in potential scaling and performance problems. The Connection Reuse draft tries to solve this by adding an alias parameter in the Via header. This parameter tells the application on the remote side to map the existing connection for future requests from the original side. The SIP Stack version 4.
Transport Support INFO method (RFC 2976)—for mid-call information exchange without changing the call state. MESSAGE method (draft-ietf-sip-message-0x)—for instant messaging. UPDATE method (RFC 3311)—to allow a client to update parameters of a session (such as the set of media streams and their codecs) without changing the dialog state. Sample code for sending/receiving this method is included.
Enhanced Features ENHANCED SIP PARSER The enhanced parser functionality provides more flexibility and allows message “correction” by the application. This functionality is available both for sending and receiving SIP messages. MULTITHREADING SIP Stack can run in internally multithreaded mode (configurable). Your application may either be single-threaded or multithreaded. SIP Stack uses locks to ensure multithreading safety at the level of individual objects, such as calllegs and transactions.
Enhanced Features 28 HP-UX C SIP Stack Programmer’s Guide
3 API CONVENTIONS INTRODUCTION The SIP Stack provides a comprehensive set of Application Programming Interface (API) structures and functions using an object-oriented methodology that are implemented in C. CONVENTIONS The SIP Stack uses specific conventions for each of the following: Return status codes Data types Parameters STATUS CODES Many API functions return status codes in order to indicate the success or failure of the requested operation.
Conventions Table 3-1 Status Codes Value Meaning RV_ERROR_NULLPTR The required pointer parameter was a NULL pointer. RV_ERROR_OUTOFRANGE A parameter that was passed to a function is out of range. RV_ERROR_DESTRUCTED The referred object was already terminated. RV_ERROR_NOTSUPPORTED The request is not supported under the current configuration. RV_ERROR_UNINITIALIZED The object is uninitialized. RV_ERROR_TRY_AGAIN The action cannot be completed—try again later.
Conventions To use these definitions, your application needs to include the RV_SIP_DEF.h file which automatically includes the rverror.h file.
Conventions 32 HP-UX C SIP Stack Programmer’s Guide
4 CREATING AN APPLICATION INTRODUCTION This chapter describes the basic code necessary to write an application using the SIP Stack, including: Initialization Event Processing Destruction Configuration Getting Module Handles INITIALIZATION Before performing any SIP-related activity, you must initialize the SIP Stack. The SIP Stack Manager API function, RvSipStackConstruct(), performs SIP Stack initialization. RvSipStackConstruct() receives the following parameters: cfgStructSize—input parameter.
Initialization Allocates memory. Initializes timers, the log file and the interface to the network. To initialize the SIP Stack 1. Declare the RvSipStackCfg structure and the RvSipStackHandle. 2. Call RvSipStackInitCfg() to fill the configuration structure with the SIP Stack default values. 3. Set your own configuration values in the configuration structure. The remainder of the SIP Stack configuration will be adjusted according to the changes you have made. 4.
Event Processing The SIP Stack configuration parameters will adjust to the new numbers you set. For more information about the SIP Stack configuration, see the Configuration chapter. EVENT PROCESSING After initializing the SIP Stack, you will need to instruct the SIP Stack to process events as they occur. You do this by calling the function, RvSipStackProcessEvents() from the same thread that constructed the SIP Stack.
Destruction DESTRUCTION The RvSipStackDestruct() function destroys the SIP Stack and frees all resources that the Stack uses. This function must be called from the same thread that constructed the Stack. CONFIGURATION The SIP Stack lets you configure SIP Stack resources and behavior.
Configuration Table 4-1 Log Filters RVSIP_LOG_ERROR_FILTER An error such as faulty application behavior, insufficient allocations, or illegal network activity. These errors are identified and handled by the SIP Stack. RVSIP_LOG_LOCKDBG_FILTER The details of all the locking operations of the Stack. RVSIP_LOG_ENTER_FILTER Indicates that an API function was called. This filter effects the logging of the Core and ADS modules only.
Configuration NETWORK CONFIGURATION The SIP Stack allows you to configure the following settings: Local IP address—the SIP Stack listening address. If you set the local IP address to “0.0.0.0”, the socket will be opened with IP=0. Local Port—the SIP Stack listening ports. If you set the port number to zero, the Stack Manager layer will use the default port (5060). Note A local address and port can be configured both for UDP and TCP transports.
Getting Module Handles PROXY CONFIGURATION The SIP Stack can be used to implement proxy applications. In this case, the SIP Stack needs to be configured with the isProxy=RV_TRUE parameter and with all other proxy-related parameters. Fore more information on the proxy configuration, see the Configuration chapter. MULTITHREADED CONFIGURATION The SIP Stack can be configured to span several internal threads. When working in multithreaded mode, the main thread inserts events into a processing queue.
Getting Module Handles 40 HP-UX C SIP Stack Programmer’s Guide
5 SIP STACK THREADING MODEL MULTITHREADING MODES The SIP Stack can work in one of three threading modes: No-threads mode—both the SIP Stack and the application work on the same single thread and therefore there is no need to protect the SIP Stack objects with locks. To avoid object locking, you need to set RV_THREADNESS_TYPE to RV_THREADNESS_SINGLE in the rvusrcongif.h file found in the common/config directory. Threadsafe mode—the SIP Stack is not multithreaded but the application is.
Multithreading Modes process it. The processing queue is used also in the no-thread and thread safety modes. However, in these modes, it is the main thread that both inserts events into the queue and then takes them out for further processing. The following events are inserted to the processing queue: Message received event—each received message is inserted into the queue and will be processed by one of the processing threads. TCP events—read, write, connect and close.
6 WORKING WITH CALL-LEGS (DIALOGS) INTRODUCTION A call-leg is a peer-to-peer SIP relationship between two User Agents (UAs) that persists for some time. The Call-leg API relates to the following entities: Call-leg (call-leg) Call-leg Manager (Call-legMgr) CALL-LEG A call-leg represents a SIP dialog as defined in RFC 3261, and is uniquely identified by the Call-ID, From and To tags. Your application can initiate calls, react to incoming calls and disconnect calls using the Call-leg API.
Call-leg API CALL-LEG API The Call-leg API contains a set of functions and function callbacks that allow you to set or examine call-leg parameters and control call-leg behavior. CALL-LEG PARAMETERS You can set or examine call-leg parameters via Call-leg Set and Get API functions. The following parameters are available: To Header, From Header, Call-ID, and CSeq When creating an outgoing call, you must set the To and From headers of the call-leg.
Call-leg API that will be placed in the top Via header of the Request message. If the local address is not set, the call-leg uses a default local address taken from the SIP Stack configuration. State Indicates the state of the session setup between two SIP UAs. You can only access the state parameter with a Get function and it is not modifiable. Direction Indicates whether the call-leg represents the incoming or outgoing side of the session.
Call-leg API Persistency Definition and Used Connection When working with TCP, the application can instruct the call-leg to try and send all outgoing requests on one TCP connection. The application can also query the call-leg about the connection used to send each request. For more information on the persistency level and persistent connection API functions, see Persistent Connection Handling of the Working with the Transport Layer chapter.
Call-leg API RvSipCallLegCancel() Sends CANCEL on an outgoing INVITE message if the final response was not yet received. This function can be used in one of the following call-leg states: PROCEEDING PROCEEDING_TIMEOUT It can also be used in one of the following re-INVITE states: REINVITE_PROCEEDING REINVITE_PROCEEDING_TIMEOUT RvSipCallLegAck() When the SIP Stack is configured to work in a manual ACK mode, the call-leg will not send an ACK message after receiving an INVITE 2xx response.
Call-leg API RvSipCallLegDisconnect() You can call RvSipCallLegDisconnect() at any point in the life span of a call-leg in order to disconnect the call. The call-leg reaction to this function depends on the current call-leg state. For example, if the call-leg is in the CONNECTED state, calling this function causes a BYE message to be sent. The call-leg then moves to the DISCONNECTING state. If the call-leg is in the IDLE state, calling RvSipCallLegDisconnect() terminates the call-leg.
Call-leg API RvSipCallLegSendPrackResponse() When the SIP Stack is configured to work in a manual PRACK mode, the application is responsible for responding to any PRACK request that is received for a previously-sent reliable provisional response. When a PRACK request is received, the call-leg PRACK state machine assumes the PRACK_RCVD state. You should then call the RvSipCallLegSendPrackResponse() function to send a response to the PRACK request.
Call-leg API When this function is used to reject a request, you cannot use the outbound message mechanism to add information to the outgoing response message. If you wish to change the response message, you must use the regular reject function in the OFFERING state. RvSipCallLegSetForceOutboundAddrFlag() You can use this function to force the call-leg to send every outgoing request to the outbound address, regardless of the message content or object state.
Call-leg API RvSipCallLegMsgToSendEv() The call-leg calls this event whenever a call-leg related message is ready to be sent. You can use this callback for changing or examining a message before it is sent to the remote party. The address resolution process will start only after this callback returns. Note You must not terminate the call-leg from this event. RvSipCallLegFinalDestResolvedEv Indicates that the call-leg is about to send a message after the destination address was resolved.
Call-leg State Machine responsible for moving the PRACK state machine using the Call-leg PRACK API. You can find the different PRACK states in the RvSipCallLegPrackState enumeration. RvSipCallLegProvisionalResponseRcvdEv() The call-leg calls this callback whenever a provisional response has been received. BYE REQUEST CALLBACKS The following two callbacks are called when a BYE request is received.
Call-leg State Machine RVSIP_CALL_LEG_STATE_IDLE The initial state of the Call-leg state machine. Upon call-leg creation, the call-leg assumes the IDLE state. It remains in this state until RvSipCallLegConnect() is called, whereupon it should move to the INVITING state. RVSIP_CALL_LEG_STATE_INVITING After calling RvSipCallLegConnect(), which will send an INVITE request, the call-leg enters the INVITING state. The call-leg remains in this state until it receives a final response from the remote party.
Call-leg State Machine RVSIP_CALL_LEG_STATE_CANCELLED Upon receiving a CANCEL request in the OFFERING state, the SIP Stack will automatically accept the CANCEL and move to the CANCELLED state. If the SIP Stack is configured to work in the manual behavior mode, your application will be responsible for responding with 487. Otherwise, 487 will be sent automatically. If you call the RvSipCallLegAccept() function in this state, the call-leg will move to the ACCEPTED state.
Call-leg State Machine this state, you can use the RvSipCallLegReInviteCreate() and RvSipCallLegReInviteRequest() functions to initiate a re-INVITE. You can also cause the call to disconnect by calling the RvSipCallLegDisconnect() function. Calling the RvSipCallLegDisconnect() function causes the state to change to DISCONNECTING.
Call-leg State Machine BASIC CALL-LEG STATE MACHINE Figure 6-1 illustrates the Basic Call-leg state machine, showing the main states involved in connecting and disconnecting calls. Connect()/ invite SENT (local inviting) 3xx Recv (redirected) INVITING REDIRECTED INVITE Recv (remote inviting) IDLE 200 OK Recv + ACK Sent (remote accepted) Connect()/ INVITE Sent (local inviting) OFFERING Accept()/ 200 OK Sent (local accepted) Authenticate()/ INVITE Sent (local inviting) 1xx Recv (remote prov. resp.
Call-leg State Machine RVSIP_CALL_LEG_STATE_PROCEEDING_TIMEOUT This state is assumed only if the enableInviteProceedingTimeoutState configuration parameter is set to RV_TRUE when the SIP Stack initializes. The call moves to this state from the PROCEEDING state when the provisional timer expires before receiving a final response. In this state, the application can cancel the call-leg or terminate it.
Call-leg State Machine REMOTE-ACCEPTED STATE MACHINE INVITING 200 OK Recv PROCEEDING 200 OK Recv REMOTE ACCEPTED Ack()/ ACK Sent Disconnect()/ BYE Sent (local disconnecting) CONNECTED DISCONNECTING Figure 6-3 BYE Recv (remote disconnected) DISCONNECTED Remote-Accepted State Machine RVSIP_CALL_LEG_STATE_MSG_SEND_FAILURE This state is assumed only if the SIP Stack is compiled with the Enhanced DNS feature.
Call-Leg Manager API MSG-SEND-FAILURE STATE MACHINE INVITING/ PROCEEDING Continue DNS() DISCONNECTING Continue DNS() Failed to send INVITE MSG SEND FAILURE Give Up() Terminate() MSG SEND FAILURE Returns to the state before the disconnecting state TERMINATE Figure 6-4 CALL-LEG MANAGER API Failed to send BYE Give Up() Terminate() TERMINATE Msg-Send-Failure State Machine The Call-legMgr controls the SIP Stack collection of call-legs.
Call-Leg Manager API According to the prototypes, you can implement any callbacks you find necessary. All callback functions are gathered together in a structure called RvSipCallLegEvHandlers. This structure is where you should set your callback function pointers and is given as a parameter to RvSipCallLegMgrSetEvHandlers(). The call-leg notifies of an event using the callback functions you implemented.
Call-Leg Manager API if (eState == RVSIP_CALL_LEG_STATE_OFFERING) { RvSipCallLegAccept(hCallLeg); } } /*===================================================================================*/ The following steps describe how to register your application callbacks. To register application callbacks 1. Declare a RvSipCallLegEvHandlers structure. 2. Initialize all the structure members to NULL using memset(). 3. Set the application defined callback in RvSipCallLegEvHandlers. 4.
Initiating a Call /*==================================================================================*/ EXCHANGING HANDLES WITH THE APPLICATION The SIP Stack enables you to create your own handle to a call-leg. This will prove useful when you have your own application call-leg database. You can provide the SIP Stack with your call-leg handle, which it must supply when calling your application callbacks.
Making a TCP Call } printf("Outgoing call-leg %x was created\n",hCallLeg); /*--------------------------------------------------------------------------------Calls the make function with the To and From strings in order to connect the call.
Making a TCP Call Sample Code The following sample code demonstrates a TCP call. /*===================================================================================*/ void AppConnectTCPCall(IN RvSipCallLegMgrHandle hCallLegMgr) { /*Handles to the call-leg and the contact addresses.*/ RvSipCallLegHandle hCallLeg = NULL; RvSipAddressHandle hLocalContactAddress = NULL; RvSipAddressHandle hRemoteContactAddress = NULL; RvChar *strFrom = "From:sip:user1@172.20.1.
Making a TCP Call /*------------------------------------------------------Fills the address handles with the contact information. -----------------------------------------------------*/ rv = RvSipAddrParse(hLocalContactAddress,strLocalContactAddress); rv1 = RvSipAddrParse(hRemoteContactAddress,strRemoteContactAddress); if(rv != RV_OK || rv1 != RV_OK) { printf("Failed to fill contact addresses\n"); return; } /*-----------------------------------------Sets the contact address to the call-leg.
Using the Outbound Message Mechanism /*===================================================================================*/ RvStatus AppCallModify(IN RvSipCallLegHandle hCallLeg) { RvStatus rv = RV_OK; RvSipCallLegInviteHandle hReInvite; /* 1. Create a re-INVITE object */ rv = RvSipCallLegReInviteCreate(hCallLeg, NULL, &hReInvite); if (RV_OK != rv) { printf("RvSipCallLegReInviteCreate() failed (rv=%d)", rv); return rv; } /* 2. Here we can set parameters to the call-leg outbound msg */ /* 3.
Call-leg re-INVITE RvChar *strFrom = "From:sip:user1@172.20.1.49:5060"; RvChar *strTo = "To:sip:user2@172.20.1.49:5060"; /*Creating a new call-leg.*/ RvSipCallLegMgrCreateCallLeg (hCallLegMgr,NULL,&hCallLeg); /*Get the outbound message object.*/ RvSipCallLegGetOutboundMsg(hCallLeg,&hMsg); /*Construct Other header in message*/ RvSipOtherHeaderConstructInMsg(hMsg,RV_TRUE,&hSubject); /*Set the other header fields.
Call-leg re-INVITE RvSipCallLegReInviteRequest() Begins a re-INVITE procedure that alters the session media description and settings. You can call this function only after the call-leg received a 2xx final response for its initial INVITE request, and when there are no other re-INVITE pending processes. You can use the outbound message mechanism to set headers and a body to the outgoing re-INVITE. Remarks: This function does not handle the call-leg Session-Timer parameters.
Call-leg re-INVITE (Modify) State Machine CALL-LEG REINVITE (MODIFY) STATE MACHINE The Call-leg Re-Invite (Modify) state machine represents the state of a reINVITE process between two SIP UAs. A re-INVITE process can occur only under the following conditions: A 2xx response was sent/received for the initial INVITE (REMOTE_ACCEPTED or CONNECTED state for an outgoing call-leg, ACCEPTED or CONNECTED for incoming call-leg). There is no other pending modify process.
Call-leg re-INVITE (Modify) State Machine RVSIP_CALL_LEG_MODIFY_STATE_REINVITE_REMOTE_ACCEPTED The remote party accepted the re-INVITE request. This state will be reported only if the manualAckOn2xx configuration parameter is set to RV_TRUE. In this case, the ACK message will not be sent automatically and the application must initiate the ACK message by calling the RvSipCallLegReInviteAck() function. RVSIP_CALL_LEG_MODIFY_STATE_REINVITE_CANCELLING A CANCEL request was sent on the re-INVITE request.
Call-leg re-INVITE (Modify) State Machine Continue DNS—send an ACK request if the failure is because of a 503 response, and try to send the request to the next address in the transaction DNS list. For more information see the Working with DNS chapter. Give up—send an ACK request if the failure is because of a 503 response, and terminate the re-INVITE object. Terminate the re-INVITE object. RVSIP_CALL_LEG_MODIFY_STATE_ACK_RCVD An ACK was received for a re-INVITE.
Call-leg re-INVITE (Modify) State Machine ReInviteRequest()/ INVITE sent IDLE INVITE recv 1xx sent (no state change) REINVITE RCVD REINVITE SENT 2xx response recv Cancel recv + 200 OK on cancel sent 1xx Recv Cancel()/ CANCEL sent REINVITE PROCEEDING Provisional timer expired REINVITE PROCEEDING TIMEOUT REINVITE REMOTE ACCEPTED 2xx response recv Accept()/Reject() final response sent final response recv + ACK sent Cancel()/ CANCEL sent ReInviteAck() ACK sent final response recv + ACK sent REI
Call-leg re-INVITE (Modify) State Machine MSG-SEND-FAILURE STATE MACHINE REINVITE SENT 503 rcvd REINVITE MSG SEND FAILURE DNS Continue DNS Giveup DNS Resend REINVITE ACK SENT REINVITE TERMINATED Figure 6-6 MSG-SEND-FAILURE STATE MACHINE WITH NETWORK ERROR OR TIMEOUT Call-leg Re-INVITE Message Send Failure State Machine REINVITE SENT DNSContinue() REINVITE MSG SEND FAILURE DNS Giveup TERMINATED Figure 6-7 Call-leg Re-INVITE Message Sent Failure State Machine with Network Error or Timeout Work
Call-leg PRACK State Machine AUTHENTICATING A RE-INVITE When a re-INVITE procedure is ended with a 401 or 407 final response, the application needs to re-send the re-INVITE with authentication information. In this case, the RVSIP_CALL_LEG_MODIFY_STATE_ACK_SENT state will have the RVSIP_CALL_LEG_REASON_AUTH_NEEDED reason.
Call-leg Transactions RVSIP_CALL_LEG_PRACK_STATE_PRACK_RCVD A PRACK request was received. RVSIP_CALL_LEG_PRACK_STATE_PRACK_FINAL_RESPONSE_SENT A PRACK final response was sent. CALL-LEG TRANSACTIONS A call-leg transaction is a transaction that is sent in the context of a call-leg but does not change the call-leg state. Such a transaction uses the call-leg identifiers (To, From and Call-ID), an increased CSeq, Route list, and Authentication information when it exists.
Call-leg Transactions RvSipCallLegTranscRequest() Sends a Request message with a given method using a given transaction. You can use this function at any call-leg state for sending requests, such as INFO. The request will have the To header, From header and Call-ID of the call-leg, and will be sent with a correct CSeq step. The request will be record routed if needed. Note Before calling this function you should create a new call-leg transaction using the RvSipCallLegTranscCreate() function.
Call-leg Transactions RvSipCallLegTranscCreatedEv() Notifies the application that a new general transaction (other than BYE or PRACK) was created and relates to the specified call-leg. In this callback, the application can replace handles with the call-leg transaction and specify whether it wishes to handle the incoming request. If so, the application will be informed of the transaction states where it will have to respond to the request.
Call-leg Transactions RVSIP_CALL_LEG_TRANSC_STATE_CLIENT_GEN_REQUEST_SENT After the application created a new call-leg transaction, it should call the RvSipCallLegTranscRequest() function with a specific method. This function will cause a request to be sent and the transaction will assume the GENERAL_ REQUEST_SENT state. RVSIP_CALL_LEG_TRANSC_STATE_CLIENT_GEN_PROCEEDING A call-leg transaction that received the first provisional response will assume the PROCEEDING state.
Call-leg Transactions TRANSACTION STATE MACHINE IDLE TranscRequest()/ request Sent MSG SEND FAILURE timeout / network error / 503 rcvd request Recvd GENERAL REQUEST SENT GENERAL REQUEST RCVD 1xx rcvd GENERAL PROCEEDING 2xx-6xx rcvd TranscResponse()/ final response sent 2xx-6xx rcvd GENERAL FINAL RESPONSE SENT GENERAL FINAL RESPONSE RCVD general linger timer DnsContinue()/ DnsGiveUp()/ TranscTerminate() Figure 6-8 TERMINATED time out T4 - UDP 0 - TCP Call-leg Transaction State Machine Samp
Call-leg Transactions /*===========================================================*/ RvStatus AppSendInfo(IN RvSipCallLegHandle hCallLeg) { RvStatus rv; RvSipTranscHandle hNewTransc; rv = RvSipCallLegTranscCreate(hCallLeg,NULL,&hNewTransc); if(rv != RV_OK) { printf("failed to create a new call-leg transaction\n"); return rv; } rv = RvSipCallLegTranscRequest(hCallLeg,"INFO",&hNewTransc); if(rv != RV_OK) { printf("failed to send INFO\n"); return rv; } return RV_OK; } /*==================================
Call-leg Transactions /*========================================================================*/ void RVCALLCONV AppCallLegTranscCreatedEvHandler( IN RvSipCallLegHandle hCallLeg, IN RvSipAppCallLegHandle hAppCallLeg, IN RvSipTranscHandle hTransc, OUT RvSipAppTranscHandle *hAppTransc, OUT RvBool *bAppHandleTransc) { RvChar method[50]; RvSipTransactionGetMethodStr(hTransc,50,method); /*Handles only INFO requests. Leaves the rest of the requests for the Stack to handle.
Call-leg Forking Support /*===================================================================*/ static void RVCALLCONV AppCallLegTranscStateChangedEvHandler( IN RvSipCallLegHandle hCallLeg, IN RvSipAppCallLegHandle hAppCallLeg, IN RvSipTranscHandle hTransc, IN RvSipAppTranscHandle hAppTransc, IN RvSipCallLegTranscState eTranscState, IN RvSipTransactionStateChangeReason eReason) { switch(eTranscState) { case RVSIP_CALL_LEG_TRANSC_STATE_SERVER_GEN_REQUEST_RCVD: RvSipCallLegTranscResponse(hC
Call-leg Forking Support RFC 3261 defines that when multiple 1xx or 2xx responses are received from different remote UAs (because the INVITE forked), each 2xx establishes a different dialog. This section describes the forking support for call-legs in the SIP Stack. TERMINOLOGY Original call-leg—The call-leg that sent the original INVITE request. The original call-leg owns the invite transaction It will handle the first response that is received from the proxy.
Call-leg Forking Support HANDLING OF MULTIPLE 2XX RESPONSES DUE TO FORKING Multiple 2xx responses may arrive at the UAC for a single INVITE request due to a forking proxy. If the dialog identifier in the 2xx response matches the dialog identifier of an existing call-leg (original or forked), the 2xx response is mapped to this call-leg. Otherwise, a new forked call-leg is created, and the 2xx response is mapped to the new call-leg.
Call-leg Forking Support The application can supply the Forked-1xx-Timer timeout value in the SIP Stack configuration. This value will apply to all forked call-legs. The application can also change the timer value for each call-leg using the call-leg API. The application may also disable this timer by setting its value to 0. A non-2xx final response should also terminate all call-legs created by the same initial request.
Call-leg Forking Support RvSipCallLegSetForkingEnabledFlag(), RvSipCallLegGetForkingEnabledFlag() Functions for setting/getting the call-leg forking-enable-flag. The forkingenabled-flag defines the call-leg behavior on receiving multiple responses due to proxy forking. If this flag is set to TRUE in the original call-leg, a new forked call-leg will be created for every 1xx/2xx response with a different, new To tag.
Call-leg Forking Support CALL-LEG FORKING SUPPORT PROCESS FLOW Figure 6-9 illustrates a typical forking scenario: UA A Proxy UA B UA C call-leg x (original) INVITE 1 2 INVITE INVITE 180 to-tag=111 4 180 to-tag=111 3 180 to-tag=222 5 200 to-tag=222 7 180 to-tag=222 6 call-leg x' (forked) 200 to-tag=222 8 ACK to-tag=222 200 to-tag=111 10 ACK to-tag=111 Figure 6-9 ACK to-tag=222 200 to-tag=111 9 ACK to-tag=111 Forking Process Call Flow The following is a description of the process
Call-leg Forking Support forked call-leg x' and supplies the 180 message to the new callleg for handling. The state of call-leg x' is updated to PROCEEDING, and its To tag value is updated to 222. Callleg x' also sets the forked-1xx-timer. 7. UA C sends a 200 response, with the To tag value of 222. The proxy forwards this final response to UAC A. 8. UA A maps the 200 response to call-leg x'. Call-leg x' reset the forked-1xx-timer, creates an ACK transmitter, and uses it to send an ACK request.
Additional Functionality Of Call-leg Layer forked1xxTimerTimeout Defines the timeout value for the forked-1xx-timer. The forked-1xx-timer is set by a forked call-leg that received the first 1xx response. If a 2xx response is received on this call-leg, the timer is released. However, if 2xx is not received, the call-leg will be terminated on timer expiration. This timeout value defines how long the call-leg will wait for a 2xx response before termination.
Additional Functionality Of Call-leg Layer If the SIP Stack is configured to enable merging support, only the first request will create a transaction. All other requests will be rejected with a 482 response. Otherwise, a new server transaction will be created for each request. For more information, see Transaction Merging Support in the the Working with Transactions chapter.
7 WORKING WITH TRANSACTIONS INTRODUCTION A SIP transaction comprises all messages, from the first request sent by the client to the server to a final (non-1xx) response to the request sent by the server to the client. The Transaction API of the SIP Stack contains a set of functions and function callbacks that can be used for two purposes. The first is for handling transactions that are related to the User Agent (UA) and not related to a call-leg. An example of such a transaction is OPTIONS.
Transaction API TRANSACTION ENTITIES The Transaction API relates to the following two entities: Transaction (transaction) Transaction Manager (TransactionMgr) TRANSACTION A transaction represents a SIP transaction as defined in RFC 3261. The transaction consists of a request (and its retransmissions) together with the response triggered by that request. Your application can initiate transactions, send requests and respond to incoming requests using the Transaction API.
Transaction API TRANSACTION PARAMETERS You can set or examine transaction parameters via transaction Set and Get API functions. The following parameters are available: To Header, From Header, Call-ID and CSeq When creating a client transaction, you must set the To and From headers of the transaction. The Call-ID and CSeq are optional. You can either set them, or the SIP Stack will generate them for you. Method Specifies the method of the SIP request.
Transaction API Outbound Message The outbound message is a handle to a message that the transaction will use for the next outgoing message. Before calling an API function that causes a message to be sent, the application can get the outbound message and add headers and a body. Response Code A 3-digit integer status code that indicates the outcome of the attempt to understand and satisfy a request. A server transaction will supply the response code when calling the RvSipTransactionResponse() API function.
Transaction API Transaction Timers and Retransmissions Count According to RFC 3261, the transaction has to set different timers during its life cycle and perform different actions when the timers expire. For example, after sending a final response, the transaction has to set a timer to the value of 32,000 msec. When this timer expires, the transaction must terminate. The values of the transaction timers are taken from the Stack configuration and are determined upon initialization.
Transaction API Is UAC 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 Is UAC parameter indicates whether or not the transaction is a client transaction. New Header Handles Some of the transaction fields are message parts. For example, the To header field is a Party header object.
Transaction API RvSipTransactionRespond() Use this function to send a provisional or final response to a transaction that received an incoming request. You can use this function with any response code and reason phrase. RvSipTransactionRespondReliable() Use this function in the INVITE-REQUEST-RECEIVED state to send a reliable provisional response. You can use this function with response codes between 101 and 199 with any reason phrase.
Transaction API PROXY TRANSACTION CONTROL The Transaction API contains a set of functions dedicated to the implementation of a Proxy server. Using these functions, you can proxy requests and responses between two UAs. RvSipTransactionSetKeyFromMsg() Initializes the transaction key from a given message.
Transaction API RvSipTransactionRespondMsg() Use this function to send a prepared Response message to the remote party. Proxy implementations will use this function in order to proxy a received response. The response is sent according to the top most Via header found in the message. RvSipTransactionIgnoreOutboundProxy() Instructs the transaction to ignore its outbound proxy. Use this function when you are about to send a message whose Request-URI was calculated using a Route header.
Transaction API RvSipTransactionStateChangedEv() This event is probably the most useful of the events that the SIP transaction reports. Through this function, you receive notifications of SIP transaction state changes and the associated state change reason and your application can act upon the state. For example, upon receipt of a SERVER_GENERAL_REQUEST_RECEIVED state notification, your application can respond with a desired response code.
Transaction State Machine For UA applications, the callback is called only for initial REFER/SUBSCRIBE methods. Applications that do not want the SIP Stack implementation for REFER and SUBSCRIBE that opens a new dialog should implement this callback. This callback will be called for the INVITE method as well only if the bDynamicInviteHandling configuration parameter is set to RV_TRUE. In this case, the application will be able to handle incoming INVITE requests above the Transaction layer.
Transaction State Machine RVSIP_TRANSC_STATE_IDLE The IDLE state is the initial state of the Transaction state machine. Upon transaction creation, the transaction assumes the IDLE state. It remains in this state until RvSipTransactionRequest() is called. If the request method is INVITE, the transaction will assume the CLIENT_INVITE_CALLING state. if the request is a general request, the transaction will assume the CLIENT_GENERAL_REQUEST_SENT state.
Transaction State Machine using a consistent interval of T2 seconds as defined in RFC 3261 (only if the transport is unreliable). Receipt of a final response will move the transaction to the CLIENT_GENERAL_FINAL_RESPONSE_RCVD state. If no final response is received when the generalRequestTimeoutTimer is expired, the transaction is terminated and assumes the TERMINATED state.
Transaction State Machine CLIENT GENERAL TRANSACTION STATE MACHINE IDLE Request( )/ Request Sent (user command) GENERAL REQUEST SENT Transaction Timeout (T1, T1*2,T1*4...
Transaction State Machine RVSIP_TRANSC_STATE_SERVER_GEN_REQUEST_RCVD Upon receipt of a request (that is not a retransmission) by a server transaction, the transaction assumes the SERVER_GENERAL_REQUEST_RECEIVED state. In this state, it is up to you to respond to the request using the transaction API. You may begin with sending provisional responses. You must end with sending a final response, or terminating the transaction. The transaction does not set any timer in this state.
Transaction State Machine SERVER GENERAL TRANSACTION STATE MACHINE IDLE Request Recv (request received) Respond (1xx)/ 1xx Send * Terminate() REQUEST RECEIVED Request Retransmission Recv/ 1xx Sent (retransmission) * Respond (2xx-6xx)/ 2xx-6xx Sent (user command) TERMINATED Terminate() Transaction Timeout (generalLingerTimer-for UDP 0-for TCP FINAL RESPONSE SENT * No state change Figure 7-2 CLIENT INVITE TRANSACTION Request Retransmission Recv/ Response Sent (retransmission) * Server General Tran
Transaction State Machine While in this state, the transaction retransmits the request message according to the rules defined in RFC 3261, and the value configured for T1. The retransmissions take place only if the transport is an unreliable transport. If no response is received when 64*T1 timer (Timer B according to RFC 3261) expires, the transaction is terminated automatically and assumes the TERMINATED state (in any transport).
Transaction State Machine RVSIP_TRANSC_STATE_CLIENT_INVITE_ACK_SENT After calling RvSipTransactionAck() which generates and sends an ACK request message, the transaction enters the CLIENT_INVITE_ACK_SENT state. The transaction retransmits the ACK request according to the reliability mechanism defined in the protocol. When entering this state, a transaction timer is set to inviteLingerTimer. When this timer expires, the transaction is terminated and assumes the TERMINATED state.
Transaction State Machine CLIENT INVITE TRANSACTION STATE MACHINE IDLE Request( )/ Request Sent (user command) INVITE CALLING Transaction Timeout (T1, T1*2,T1*4...
Transaction State Machine RVSIP_TRANSC_STATE_SERVER_INVITE_REQUEST_RCVD Upon receipt of an INVITE request (that is not a retransmission) by a server INVITE transaction, the transaction assumes the SERVER_INVITE_REQUEST_RECEIVED state. In this state, it is up to you to respond to the request using the Transaction API. You may begin with sending provisional responses. You must end with sending a final response, or terminating the transaction.
Transaction State Machine expires, the transaction automatically sends a 500 response. Receipt of the PRACK and responding to it moves the transaction to the SERVER_INVITE_PRACK_COMPLETED state. RVSIP_TRANSC_STATE_SERVER_INVITE_PRACK_COMPLETED While in the SERVER_INVITE_REL_PROV_RESPONSE_SENT state, the INVITE server transaction waits for a PRACK process to be completed. The PRACK process is handled by a separate general server transaction.
Transaction State Machine SERVER INVITE TRANSACTION STATE MACHINE IDLE Invite Request rcvd (Request Rcvd) Invite rcvdsend last 1xx response* Respond(1xx)/ 1xx sent * RespondMsg (2xx (for proxy only)) INVITE RCVD Respond Reliable(1xx) reliable 1xx sent time out(T1, 2*T1, 4*T1,...) retransmission PROXY 2xx RESPONSE SENT Respond (2xx-6xx) REL PROV SENT Respond (2xx-6xx) Prack Recvd Respond Reliable(1xx) Respond + response sent reliable 1xx sent (500) on time out time out (T1, 2*T1, ...
Transaction State Machine CLIENT CANCEL TRANSACTION A transaction may assume any of the following states in the Client CANCEL state machine: RVSIP_TRANSC_STATE_CLIENT_CANCEL_SENT When calling the RvSipTransactionCancel() function, a new Client CANCEL transaction is created and a CANCEL request is sent. The client CANCEL transaction assumes the CLIENT_CANCEL_SENT state.
Transaction State Machine CLIENT CANCEL TRANSACTION STATE MACHINE IDLE Cancel( )/ Cancel Sent (user command) Transaction Timeout (T1, T1*2,T1*4...
Transaction State Machine RVSIP_TRANSC_STATE_SERVER_CANCEL_REQUEST_RCVD Upon receipt of a CANCEL request that is not a retransmission by a server transaction, the transaction assumes the SERVER_CANCEL_REQUEST_RECEIVED state. In this state, it is up to you to respond to the request with the Transaction API functions. You may begin with sending provisional responses. You must end with sending a final response, or terminating the transaction. This state is used only if the SIP Stack is configured as a proxy.
Transaction State Machine SERVER CANCEL TRANSACTION STATE MACHINE IDLE Cancel Received Cancel Retransmission rcvd/ 1xx sent * CANCEL REQUEST RCVD Final response sent Cancel Received + Final Response Sent Cancel Retransmission rcvd/ Response Sent (retransmission)* CANCEL FINAL RESPONSE SENT Terminate(), Transaction Timeout (general linger timer - for UDP, 0 - for TCP) * No state change Figure 7-6 TERMINATED Server CANCEL Transaction State Machine TRANSACTION ADVANCED STATES Transaction states t
Transaction State Machine RVSIP_TRANSC_STATE_CLIENT_MSG_SEND_FAILURE The transaction assumes this state when the sending of a request fails due to timeout (timer B or F expired and no response was received), network error or 503 final response. In this state it is your responsibility to decide whether to terminate the transaction or call the continue-DNS function that opens a new transaction and sends the message to the next address in the DNS list.
Transaction Manager API TRANSACTION MANAGER API The TransactionMgr controls the SIP Stack collection of transactions. You use the Transaction Manager API to register application callbacks with the SIP Stack and to create new transactions. TRANSACTION MANAGER CONTROL The following API functions are provided for TransactionMgr control: RvSipTranscMgrCreateTransaction() You use this function to create a new transaction.
Transaction Manager API RvSipTranscMgrCreateServerTransactionFromMsg() Creates a new Server transaction from a request message. This function will be used by stateless proxy applications. A stateless proxy does not open a transaction for incoming requests. However, according to RFC 3261, if a stateless proxy wishes to reject a request, it needs to handle this request in a stateful manner. For this, the stateless proxy needs to instruct the SIP Stack to open a server transaction from the request message.
Using Transactions USING TRANSACTIONS The following sections present various ways of using transactions accompanied by code samples. These sections include: Registering Application Callbacks Exchanging Handles with the Application Sending a Request Using the Outbound Message Mechanism Transaction Merging Support REGISTERING APPLICATION CALLBACKS To register an application callback, you must first define the callback according to the prototype.
Using Transactions /*==========================================================================*/ static void RVCALLCONV AppTransactionCreatedEvHandler( IN RvSipTranscHandle hTransc, IN void *context, OUT RvSipTranscOwnerHandle *phAppTransc, OUT RvBool *b_handleTransc) { RvChar strMethod[20]; *phAppTransc = NULL; *b_handleTransc = RV_FALSE; RvSipTransactionGetMethodStr(hTransc,20,strMethod); if(strcmp(strMethod,”OPTIONS”) == 0) { *b_handleTransc = RV_TRUE; } } /*====================================
Using Transactions /*===================================================================*/ void RVCALLCONV AppTransactionStateChangedEvHandler( IN RvSipTranscHandle hTransc, IN RvSipTranscOwnerHandle hAppTransc, IN RvSipTransactionState eState, IN RvSipTransactionStateChangeReason eReason) { RvStatus rv; switch(eState) { case RVSIP_TRANSC_STATE_SERVER_GEN_REQUEST_RCVD: rv = RvSipTransactionRespond(hTransc,200,NULL); if(rv!= RV_OK) { printf("Failed to respond to the request"); } break; default: break; } } /
Using Transactions /*==================================================================================*/ void SetTransactionEvHandlers(RvSipTranscMgrHandle hMgr) { /*step 1*/ RvSipTransactionEvHandlers appEvHandlers; /*step 2*/ memset(&appEvHandlers,0,sizeof (RvSipTransactionEvHandlers)); /*step 3*/ appEvHandlers.pfnEvTransactionCreated = AppTransactionCreatedEvHandler; appEvHandlers.
Using Transactions /*========================================================================*/ RvStatus AppSendOptionsRequest(RvSipTranscMgrHandle hMgr) { RvSipTranscHandle RvStatus hTransc; /*Handle to the transaction.*/ rv; RvChar *strFrom = "From:sip:user1@172.20.0.1:5060"; RvChar *strTo = "To:sip:user2@172.20.10.11:5060"; RvChar *strRequestUri = "sip:172.20.0.1:5060"; RvChar *strMethod = "OPTIONS"; RvInt32 cseq = 5; /*-------------------------Creates a new transaction.
Using Transactions Allow: INVITE,ACK,CANCEL,BYE,OPTIONS Accept: application Accept-Encoding: gzip To add the headers 1. Get the outbound message from the transaction using the RvSipTransactionGetOutboundMsg() function. 2. Use the message API functions to add the above headers. 3. Send the 200 response using the RvSipTransactionRespond() function. Sample Code The following code demonstrates the steps described above.
Using Transactions RvSipTransactionGetOutboundMsg(hTransc,&hMsg); /*Adds the 'Allow: INVITE,ACK,CANCEL,BYE,OPTIONS' header*/ RvSipAllowHeaderConstructInMsg(hMsg,RV_FALSE,&hAllow); RvSipAllowHeaderSetMethodType(hAllow,RVSIP_METHOD_INVITE,NULL); RvSipAllowHeaderConstructInMsg(hMsg,RV_FALSE,&hAllow); RvSipAllowHeaderSetMethodType(hAllow,RVSIP_METHOD_ACK,NULL); RvSipAllowHeaderConstructInMsg(hMsg,RV_FALSE,&hAllow); RvSipAllowHeaderSetMethodType(hAllow,RVSIP_METHOD_CANCEL,NULL); RvSipAllowHeaderConstructInMsg(h
Using Transactions According to RFC 3261, in the case of several incoming transactions all caused by a single request message, the UAS should handle only one request, and reject all others with the 482 (Loop Detected) response. This procedure is called “Merging”. Figure 7-8 illustrates the message flow of a merging scenario.
Using Transactions UA2 receives two INVITE requests with same request identifiers, but with different Via headers. DISABLING MERGING SUPPORT 2. UA2 handles the first INVITE request as usual—it creates a call-leg in the OFFERING state, and waits for the application decision of whether to accept or reject this request. 3. UA2 discovers that the second INVITE request has the same request identifiers, and therefore rejects it with 482. 4.
8 WORKING WITH REGISTER-CLIENTS INTRODUCTION The SIP REGISTER request allows a client to inform a Proxy or redirect server of the addresses at which the client can be reached. The Register-Client API of the SIP Stack enables you to register with a Proxy or a SIP server, refresh registration when needed, and send authentication information to the server, as required.
Working with Handles SINGLE-USER VERSUS MULTI-USER APPLICATIONS By default, the Register-ClientMgr owns all the register-clients. The RegisterClientMgr is responsible for generating a Call-ID once and supplying it to all its register-clients. The Register-ClientMgr is also responsible for the CSeq-Step counter. Each register-client will receive the CSeq-Step current count from the Register-ClientMgr immediately before sending a new REGISTER request.
Register-Client API REGISTER-CLIENT API The Register-Client API contains a set of functions and function callbacks that allow you to set or examine register-client parameters, control REGISTER requests and respond to network events. REGISTER-CLIENT PARAMETERS You can set or examine register-client parameters via Register-Client API Set and Get functions.
Register-Client API CSeq-Step The CSeq-Step is either managed by the register-client (for stand-alone registerclients) or by the Register-ClientMgr. Stand-alone register-clients increase the CSeq-Step for every REGISTER request. Non-stand-alone register-clients receive the CSeq-Step from the Register-ClientMgr each time they wish to send a REGISTER Request. The Register-ClientMgr keeps a global CSeq and increases it each time a new REGISTER request is sent.
Register-Client API Register-client Transaction Timers and Retransmission Count The SIP Stack configuration determines the value of the timers and retransmission count for all the SIP Stack transactions. The application can use a set function to change the different timer values of the register-client transactions. The application can also control the number of retransmissions that the transactions perform.
Register-Client API RvSipRegClientMake() After creating a register-client, you can use this function to set the To and From headers and the contact and Registrar addresses in the register-client, and send the REGISTER request. You can use this function if you have all the needed fields in textual format.
Register-Client State Machine new state. For example, upon receipt of an UNAUTHENTICATED state notification, your application can use the RvSipRegClientAuthenticate() to resend the registration request with authentication information. RvSipRegClientMsgToSendEv() The register-client calls this event whenever a register-client related message is ready to be sent. You can use this callback for changing or examining a message before it is sent.
Register-Client State Machine BASIC REGISTERCLIENT STATES RVSIP_REG_CLIENT_STATE_IDLE The IDLE state is the initial state of the Register-Client state machine. Upon register-client creation, the Register-Client assumes the IDLE state. The register-client remains in this state until RvSipRegClientRegister() is called, whereupon it moves to the REGISTERING state.
Register-Client State Machine RVSIP_REG_CLIENT_STATE_REGISTERED This state indicates that the register-client successfully registered with the Registrar. The register-client reaches this state when a 2xx final response is received. The register-client is not terminated although the registration process has successfully terminated. You can use this register-client for refreshing the registration by re-using the RvSipRegClientRegister() function.
Register-Client State Machine BASIC STATE MACHINE IDLE Register() / REGISTER sent (User request) REDIRECTED Register()/ REGISTER sent (User request) 4xx, 5xx, 6xx Recvd (request failure) (server failure) (global failure) 3xxRecvd (redirected) 1xx Rcvd REGISTERING Authenticate() / authenicated REGISTER sent (user request) timeout Recvd Register()/ REGISTER sent (user request) 2xx Recvd (success) FAILED 401, 407 Recvd (Unauthenticated) UNAUTHENTICATED REGISTERED Terminate() Terminate() TERMIN
Register-Client State Machine RVSIP_REG_CLIENT_STATE_MSG_SEND_FAILURE This state is assumed only if the SIP Stack works with the Enhanced DNS feature. The register-client moves to this state when it failed to send a request (the register-client received a network error, 503 response or time-out on the request). In this state your application can: Continue DNS—try to send the request to the next address in the transaction DNS list. For more information see the Working with DNS chapter.
Register-Client Refresh Mechanism REGISTER-CLIENT REFRESH MECHANISM When a REGISTER request receives a 2xx class response, the register-client assumes the REGISTERED state. This state indicates that the register-client is registered with the requested Registrar according to its To, From, Expires and Contact headers. The register-client is not terminated and remains in the REGISTERED state until the application causes a change in the state of the object.
Registering Application Callbacks /*===================================================================*/ typedef void (RVCALLCONV * RvSipRegClientStateChangedEv)( IN RvSipRegClientHandle hRegClient, IN RvSipAppRegClientHandle hAppRegClient, IN RvSipRegClientState eNewState, IN RvSipRegClientStateChangeReasonm eReason); /*===================================================================*/ You can implement any callbacks you find necessary, according to the callback function prototypes in the
Registering Application Callbacks Sample Code /*===================================================================================*/ /*Implements the register-client state changed event handler. Prints the handle of each successfully registered register-client and terminates it.
Exchanging Handles with the Application /*===================================================================================*/ void SetRegisterClientEvHandlers( RvSipRegClientMgrHandle hMgr) { /*Step 1*/ RvSipRegClientEvHandlers appEvHandlers; /*Step 2*/ memset(&appEvHandlers, 0, sizeof(RvSipRegClientEvHandlers)); /*Step 3*/ appEvHandlers.
Initiating a Register-Client To initiate a Register-Client 1. Declare a handle to the new register-client. 2. Define the To, From, Registrar and Contact addresses as strings. 3. Call the RvSipRegClientMgrCreateRegClient() function. This enables you to exchange handles with the SIP Stack. 4. Call the RvSipRegClientMake() function, supplying the handle to the register-client and the string addresses defined in step 3. Calling this function sends a REGISTER request to the requested Registrar.
Initiating a Register-Client 3. Creates a new register-client. ----------------------------------------------------*/ rv = RvSipRegClientMgrCreateRegClient(hRegClientMgr, NULL, &hRegClient); if (rv != RV_OK) { printf("Failed to create new register-client"); return; } /*--------------------------------------------------4. Calls the “make” function to register with the register-client.
Initiating a Register-Client 146 HP-UX C SIP Stack Programmer’s Guide
9 WORKING WITH SIP MESSAGES INTRODUCTION The SIP Stack provides a flexible API for working with SIP messages and message parts, such as headers and addresses. The SIP Stack uses object-oriented methodology and treats messages and message parts as objects.
Working with Handles Min-SE header Other header Party header (To and From headers) RAck header Refer To header Referred By header Replaces header Retry-After header Route Hop header (Route, Record-Route, Service-Route and Path headers) RSeq header Session-Expires header Subscription-State header Via header WORKING WITH HANDLES Message API functions define handles for the different types of messages. For example: RvSipMsgHandle—defines the handle to a message.
Message Objects MESSAGE OBJECTS A message holds all message parts, which include the message start line, one or more header fields and an optional message-body. The message holds most of its headers in a sequential list. The Call-ID, To, From, CSeq, Content-Type and Content-Length headers are held separately. These headers can only appear once in a SIP message. Figure 9-1 illustrates a SIP message.
Header Objects HEADER OBJECTS The SIP Stack has several types of header objects. Each header object represents a SIP header. The header object holds the header fields according to the header BNF definition. Figure 9-2 illustrates a To header object. (To and From SIP headers are both kept in a Party header object.) To: Bob;tag=314159 Display name = "Bob" Tag = "314159" Party Header Object Address Object User = "UserB" Host = "there.com" .......
SIP Stack Message API SIP STACK MESSAGE API SIP Stack Message API functions can be categorized as follows: CONSTRUCTORS You use constructors to create new objects. GET AND SET FUNCTIONS Get and Set functions are the only way to access object fields. The following rules apply to Get and Set functions: Setting parameters The parameter you supply is always copied into the object. Getting string parameters You must supply a buffer. The Get function will copy the string into this buffer.
Working with Headers /*==========================================================================*/ void UsingHeaders(RvSipPartyHeaderHandle ToHeader) { int length; RvChar* strBuffer; RvSipAddressHandle hAddress; /*Gets and sets header parameters:*/ /*Displays name.
Working with SIP Messages WORKING WITH SIP MESSAGES The SIP Stack Message API provides a set of functions for accessing, encoding, parsing and adding new headers to messages. READING AND MODIFYING SIP MESSAGES The Message API provides a set of functions for reading and modifying various message parts such as the start-line field, headers and body.
Working with SIP Messages return RV_ERROR_UNKNOWN; } /*Gets the From header value--direct access.*/ fromHeader = RvSipMsgGetFromHeader(hMsg); if(fromHeader != NULL) { /*Performs an action with the From Header.*/ } /*Gets all the Via header values using the header list functions.*/ viaHeader = (RvSipViaHeaderHandle)RvSipMsgGetHeaderByType(hMsg, RVSIP_HEADERTYPE_VIA, RVSIP_FIRST_HEADER, &listElem); while (viaHeader != NULL) { /*Performs an action with the Via header that was received.*/ /*Gets the next one.
Working with SIP Messages To encode a SIP message 1. Call the RvSipMsgEncode() function with the message handle and the pool handle. The Encode() function receives the pool handle and returns a handle to the new page containing the encoded string and the length of the encoded string. 2. Allocate a buffer of the same length as the retrieved length, +1 if you want to place '\0' at the end. 3.
Working with SIP Messages /*===================================================================================*/ void EncodeMessage(RvSipMsgHandle hMessage, HRPOOL hPool) { RvUint32 length = 0; HPAGE hPage; RvStatus status; RvChar *msgBuf; status = RvSipMsgEncode(hMessage, hPool, &hPage, &length); if (status != RV_OK) { printf("RvSipMsgEncode failed. status is %d\n",status); return; } /*Allocate a consecutive buffer.
Working with SIP Messages PARSING To get a header object from a string encoded according to the specifications of RFC 3261, you should use the Parse() or ParseValue() function. Sample Code The following code demonstrates how to parse a textual Contact header into a Contact header object. /*==================================================================================*/ void ContactHeaderParse(IN RvSipContactHeaderHandle hContact) { RvStatus status; RvChar* strContact = "Contact: Carol Lee
Stand-alone Headers /*===================================================================================*/ RvStatus createHeadersInMessage (HRPOOL hPool, RvSipMsgHandle hMsg) { RvStatus status; RvSipAddressHandle uri; RvSipPartyHeaderHandle fromHeader; RvSipContactHeaderHandle contactHeader; /*Creates a From header in the message and creates and set a URL object in it.
Stand-alone Headers CREATING A STAND-ALONE HEADER When constructing a stand-alone header, you must provide the MessageMgr handle and a memory page. The Construct() function creates the header object on the given page and returns a handle to the new header object. For more information about the memory pool, see the Memory Pool chapter. Sample Code The following code demonstrates the creation of a stand-alone CSeq header.
Stand-alone Headers Sample Code The following code demonstrates how to insert CSeq and Via headers into a message: /*===========================================================*/ RvStatus SetStandAloneInMsg(RvSipMsgHandle hMsg, RvSipCSeqHeaderHandle hCSeq, RvSipViaHeaderHandle hVia) { RvSipHeaderListElemHandle listElem; /*Sets CSeq header in the message.*/ RvSipMsgSetCSeqHeader(hMsg, hCSeq); /*Pushes the Via header in the message.
Creating a New SIP Message CREATING A NEW SIP MESSAGE You can create a new message by performing the following steps: To create a new message 1. Create a message with the Construct() function. 2. Set the start-line values: request-line values, if this is a request, or the status-line values, if this is a response. 3. Add headers as required. 4. Add a message body as required. Sample Code The following code demonstrates how to create a new message.
Creating a New SIP Message return NULL; /*Sets the URL parameters by parsing the encoded URL or setting parameters with the Set functions.*/ RvSipAddrParse(uri, "sip:john@acme.com"); /*Adds other headers as needed...*/ /*Adds message body.
Using Compact Form USING COMPACT FORM SIP provides a mechanism for representing header field names in a compact form. For example, the header, “from: Bob ” will become “f: Bob ” when compact form is used. “SET” COMPACT FORM FUNCTIONALITY Table 9-1 represents the headers that can accept compact form and the API functions that should be used to set compact form to each header.
Handling Messages with Syntax Errors RvSipMsgGetXXXCompactForm(). FORCING COMPACT FORM ON THE ENTIRE MESSAGE The application can instruct a message to force all of its headers to use compact form. This is done by calling the function RvSipMsgForceCompactForm(). When such a message is encoded, all headers that can take compact form will be encoded with compact form. Headers that handled by the Stack as Other headers and are added to the message by the application will not use compact form.
Handling Messages with Syntax Errors BAD SYNTAX HEADER The general grammar of any SIP header is “header-name: header-value”. When the SIP Stack parses a header, it first constructs the header object according to the header-name part and then parses the header-value into the object-specific fields. If the header-value contains syntax errors, it is kept in the object as a single string in the StrBadSyntax parameter. All other header fields are set to NULL or UNDEFINED.
Handling Messages with Syntax Errors In the callback functions, the application can query the message for its bad message parts and fix syntax errors. The application should then instruct the Stack on how to continue with the message processing with one of the following options: Discard the message Reject the message Continue message processing The three options are defined in the RvSipTransportBsAction enumeration, where “Bs” stands for bad syntax. For more information, see the SIP Stack Reference Guide.
Handling Messages with Syntax Errors Figure 9-5 illustrates how the Stack handles a bad-syntax message across layers when the application chooses the “continue processing” option. New message with syntax errors is received Parse the message, keep bad syntax parts in the StrBadSyntax parameter B.
Handling Messages with Syntax Errors FIXING BAD SYNTAX MESSAGES There are cases where the application knows in advance that a certain header from the remote party will be received with a syntax error. This is usually the case when the application needs to work with another application that is not fully standard-compliant. The error can sometimes be crucial for SIP Stack message processing, such as an error in the top Via header.
Handling Messages with Syntax Errors Message API and retrieve the bad-syntax start line and fix it. Using this callback, the application should instruct the Stack on how to handle the message—discard, reject or continue processing. Note A message with a bad syntax start line is not recognized as a request or a response. Therefore, if you wish the Stack to continue the message processing, you must fix the start line using the RvSipMsgStartLineFix() function.
Handling Messages with Syntax Errors You can use this function in the RvSipTransportBadSyntaxStartLineMsgEv() callback to check and fix the defected start-line. RvSipMsgGetHeaderExt(), RvSipMsgGetHeaderByTypeExt(), RvSipMsgGetHeaderByNameExt() These three function extend the functionality of functions that already exists in the SIP Stack API.
Handling Messages with Syntax Errors RvSipXXXHeaderGetStrBadSyntax() Gets the bad-syntax string from the header object. Use this function in the RvSipTransportBadSyntaxMsgEv() callback implementation to see the badsyntax header-value. RvSipXXXHeaderSetStrBadSyntax() Sets a bad syntax string to the header object and marks the header as a badsyntax header. RvSipXXXHeaderFix() Fixes a bad syntax header. This function parses a given correct header-value string to the supplied header object.
Handling Messages with Syntax Errors /*===================================================================================*/ RvStatus RVCALLCONV AppTransportBadSyntaxMsgEv( IN RvSipTransportMgrHandle IN RvSipAppTransportMgrHandle hAppTransportMgr, hTransportMgr, IN RvSipMsgHandle hMsgReceived, OUT RvSipTransportBsAction *peAction) { RvStatus rv = RV_OK; void* pHeader = NULL; RvSipHeaderType eHeaderType; RvSipHeaderListElemHandle hElem; *peAction = RVSIP_TRANSPORT_BS_ACTION_CONTINUE_PROCE
Handling Messages with Syntax Errors In this sample, the application receives a CSeq without the method part. To fix the CSeq header, the application takes the method from the message request line and uses the RvSipCSeqHeaderFix() function to fix the CSeq header.
Working With Multipart MIME } /*Gets the method string from the message request line.*/ rv = RvSipMsgGetStrRequestMethod(hMsg, startLineMethodStr, startLineMethodStrLen, &startLineMethodStrLen); if(rv != RV_OK) { printf("Failed to get method string from message start-line"); return RV_ERROR_UNKNOWN; } /*Creates the correct header value string by concatenating the bad-syntax string with the method.
Working With Multipart MIME The SIP Stack Message API provides a set of functions that enables you to Construct, Parse and encode multipart MIME bodies. MESSAGE MULTIPART BODY STRUCTURE The SIP Stack provides two types of objects for working with multipart MIME bodies—the Body object and the Body Part objects. Both the Body and the Body Part objects are identified using handles.
Working With Multipart MIME Figure 9-6 shows the structure and relationship between the Body and the Body Part objects.
Working With Multipart MIME Figure 9-7 is an example of a SIP message with a multipart MIME body. Each of the message parts is related to its corresponding object. INVIT E sip:user@hp.com SIP/2.0 … Message Headers and Start Line CSeq: 1 INVITE MIME-Version: 1.
Working With Multipart MIME /*==================================================================================*/ void AppSetContentTypeToMsg( IN RvSipMsgHandle hMsg, IN RvSipContentTypeHeaderHandle hContentType) { RvStatus rv; RvSipBodyHandle hBody; /*Gets the body object of the message.*/ hBody = RvSipMsgGetBodyObject(hMsg); if (NULL == hBody) { /*Constructs a new body object if there is no body object for this message.
Working With Multipart MIME the Content-Disposition header of a Body Part, use the functions, RvSipBodyPartGetContentDisposition() and RvSipBodyPartSetContentDisposition(). All headers other than Content-Type and Content-Disposition are held in a list within the Body Part object. RvSipOtherHeaderHandle represents each of these headers. This also refers to headers that have special objects defined for them in the SIP Stack, such as To, From, CSeq, etc.
Working With Multipart MIME /*==================================================================================*/ void AppParseMultipartMixedBody(IN RvSipMsgHandle hMsg) { RvSipBodyHandle hBody; RvSipBodyPartHandle hBodyPart; RvUint32 length; RvChar *strBody; RvStatus rv; /*Gets the body object of the message.*/ hBody = RvSipMsgGetBodyObject(hMsg); if (NULL == hBody) { return; } /*Gets the body string from the body object.
Working With Multipart MIME if (RV_OK != rv) { printf("Failed to get body part"); return; } while (NULL != hBodyPart) { /*Do something with the body part ... */ /*Gets the next body part in the list.
Working With Multipart MIME /*=========================================================================================*/ void AppCreateMultipartBodyFromBodyParts( IN RvChar *strBodyPart1, IN RvChar *strBodyPart2, INOUT RvSipBodyHandle hBody) { RvSipBodyPartHandle hBodyPart; RvSipContentTypeHeaderHandle hContentType; RvStatus rv; /*Constructs the Content-Type header within the given body object. Note that the received Body was constructed outside of this function.
Working With Multipart MIME /*Constructs the new body part within the given body object.*/ rv = RvSipBodyPartConstructInBody(hBody, RV_FALSE, &hBodyPart); if (RV_OK != rv) { printf("Failed to construct body part"); return; } /*Parses the body part string.
Working With Multipart MIME To check if a Body object is parsed, use the RvSipBodyGetBodyPart() function with location RVSIP_FIRST_ELEMENT. A non-NULL value will indicate a parsed Body. A Body object that is not of type Multipart can be represented by a string only. You can get the Body string using the functions, RvSipBodyGetBodyStrLength() and RvSipBodyGetBodyStr(). You can set the Body string using the function, RvSipBodySetBodyStr().
10 AUTHENTICATION INTRODUCTION The authentication mechanism enables a User Agent Client (UAC) to prove authenticity to servers or proxies which require authentication. The SIP Stack supports SIP authentication using the HTTP Digest Scheme as described in RFC 3261 and RFC 2617. The SIP Stack authenticator object (authenticator) is responsible for applying the authentication mechanism in both the client and server authentication process.
Introduction 1. A server responds to the originator of an incoming request with a 401 Unauthorized response. A Proxy server responds with a 407 Proxy Authentication Required response. These responses each include a special Authentication header with information required by the UAS in the Authentication process. The information included in the Authenticator header is called “challenge”. AUTHENTICATOR OBJECT 2.
Client Authentication Implementation WORKING WITH THE AUTHENTICATOR To work with the authenticator, you should first get the authenticator handle from the SIP Stack. RvSipAuthenticatorHandle defines the handle to the authenticator. You can receive this handle by calling RvSipStackGetAuthenticatorHandle(). You use this handle to set your application callbacks, and to activate other authenticator functions. The authenticator is responsible for both client and server authentication.
Client Authentication Implementation RvSipAuthenticatorMD5EntityBodyEv() Notifies the application that it should supply the hash result on the message body (MD5(entity-body)). The body hash value is needed when the required quality of protection (qop) was set to “auth-int”. Note This callback supplies the message as a parameter. However, it is called before the msgToSend() callback of any SIP Stack object.
Client Authentication Implementation IMPLEMENTING THE MD5 CALLBACK FUNCTION The input string to the MD5 algorithm is placed on an rpool page. When calling this callback, the authenticator supplies the RPOOL_Ptr structure which holds the memory pool, page and offset of the input string. To implement the MD5 callback function 1. Allocate a consecutive buffer. 2. Use RPOOL_CopyToExternal() to copy the string to the buffer. 3. Give this buffer as an input to the MD5 algorithm. 4.
Client Authentication Implementation /*Implements the MD5 algorithm.*/ MD5Init(&mdc); MD5Update(&mdc, strInput,strlen(strInput)); MD5Final(digest, &mdc); /*Changes the digest into a string format.*/ MD5toString(digest, strResponse); /*Inserts the MD5 output to the page that is supplied in pRpoolMD5Output.
Client Authentication Implementation pRpoolUserName->hPool, pRpoolUserName->hPage, (void*) strAuthUserName, strlen(strAuthUserName) + 1, &(pRpoolUserName->offset)); /*Appends the password to the given page.
Client Authentication Implementation &authEvHandlers, sizeof(RvSipAuthenticatorEvHandlers)); return status; } /*=========================================================================================*/ AUTHENTICATION OBJECT CONTROL Each WWW-Authenticate/Proxy-Authenticate header that is received in a 401/ 407 response message is saved in the relevant SIP Stack object (such as regclient and call-leg) for the entire lifetime of the object.
Client Authentication Implementation Sample Code The following code sample demonstrates how to get the authentication objects from a call-leg, and how to set the shared secret in each object.
Client Authentication Implementation You can construct an Authentication header and set the fields using the Message API. You should then set the header to the authenticator, using RvSipAuthenticatorSetProxyAuthInfo(). The authenticator uses the header for building the Proxy-Authorization header that is inserted into the initial request. The following API functions supply in-advance authentication control: RvSipAuthenticatorSetProxyAuthInfo() Sets a Proxy-Authorization header to the authenticator.
Client Authentication Implementation Sample Code The following code demonstrates how to set the Proxy-Authenticate header for authenticating messages in advance. /*==========================================================================*/ RvStatus SetProxyAuthenticateHeader ( RvSipAuthenticatorHandle HRPOOL hPool, HPAGE hPage) hAuthenticator, { RvStatus status; RvSipAuthenticationHeaderHandle hProxyAuth; /*---------------------------------------Constructs the Proxy-Authenticate header.
Client Authentication Implementation RVSIP_AUTH_ALGORITHM_MD5,NULL); /*Sets the QOP options.*/ RvSipAuthenticationHeaderSetQopOption(hProxyAuth, RVSIP_AUTH_QOP_AUTH_ONLY); /*-----------------------------------Sets the Proxy-Authenticate header.
Server Authentication Implementation SERVER AUTHENTICATION IMPLEMENTATION Call-leg, subscription and server transactions can authenticate incoming requests, and respond with 401/407 when the authentication process fails. The originator credentials are located in an Authorization header. An incoming request message may contain more than one Authorization header.
Server Authentication Implementation When the SIP Stack receives a new request message, the server assumes a suitable state that indicates that the request was received. For example the OFFERING state of a call-leg indicates that an INVITE request was received. At this point, if the application wishes to verify the authenticity of the originator, it may begin the server authentication procedure.
Server Authentication Implementation If the user was not found in the database, the application may call the RvSipXXXAuthProceed(SKIP_HEADER) function in order to continue with the loop, finding the next Authorization header (back to step 3). If the SIP Stack does not support the credentials, the application can try to verify the credentials by itself. By calling the RvSipXXXAuthProceed(SUCCESS) function, the application indicates that the credentials were verified by it.
Server Authentication Implementation Incoming Request stateChangedEv( RequestRcvd) RvSipXXXAuthBegin Does authorization header exist in the incoming request? No RvSipXXXAuthCompletedEv( Failure) Yes RvSipXXXRespondUnauthen ticated(401) No RvSipXXXAuthCredentialsFo undEv(header) Are credentials supported? Yes Applcation verifies credentials by itself Was user found in database? yes No Were credentials verified? No RvSipXXXAuthProceed( USE_PW, password) yes No (Continue with loop) RvSipXXXA
Server Authentication Implementation SERVER AUTHENTICATION FUNCTIONS AND CALLBACKS Server authentication may be implemented above the Call-leg, Subscription or Transaction layers (for proxies). Because of this, there are three sets of functions, one for each layer. CALL-LEG SERVER AUTHENTICATION FUNCTIONS The following functions are used for Call-leg server authentication: RvSipCallLegAuthBegin() Begins the server authentication process.
Server Authentication Implementation RvSipCallLegRespondUnauthenticatedDigest() Responds with a 401 or 407 message. You supply this function with the challenge parameters. The SIP Stack will use these parameters to create an Authentication header. This header will be placed in the response message. .CALL-LEG SERVER AUTHENTICATION CALLBACKS RvSipCallLegAuthCredentialsFoundEv() This callback notifies the application that credentials were found in the request message.
Server Authentication Implementation RvSipTransactionAuthProceed() RvSipTransactionRespondUnauthenticated() RvSipTransactionRespondUnauthenticatedDigest() TRANSACTION SERVER AUTHENTICATION CALLBACKS The server authentication callback functions of the Transaction layer are similar to the callback functions of the Call-leg layer.
Server Authentication Implementation Figure 10-2 shows the event flow of a successful server authentication procedure. Server Transaction Layer Client Application request stateChangeEv Check if authentication is needed RvSipTransactionAuthBegin(hTransc) Get Authorization headers from the request message RvSipTransactionCredentialsFoundEv(hTransc, header, isSupportedCredentails) Check the given credentails. assume unknown realm.
Server Authentication Implementation /*=========================================================================================*/ RvChar* g_strSrvAuthRealm = "HP Realm"; void AppAuthCredentialsFoundEv( IN RvSipCallLegHandle hCallLeg, IN RvSipAppCallLegHandle hAppCallLeg, IN RvSipTranscHandle hTransc, IN RvSipAuthorizationHeaderHandle hAuthorization, IN RvBool bCredentialsSupported) { RvStatus rv; RvChar strName[50], strRealm[50], strNonce[50]; RvChar strPW[50]; RvInt32 actualLen; RvBool toS
Server Authentication Implementation /*---------------------------------------------------------------------------------g_strSrvAuthNonce and g_strSrvAuthRealm are global parameters, holding the application's nonce and realm values. -----------------------------------------------------------------------------------*/ if(strcmp(strNonce, g_strSrvAuthNonce)!=0) { printf("incorrect nonce %s.
Server Authentication Implementation hCallLeg, hTransc, RVSIP_TRANSC_AUTH_ACTION_SKIP, NULL, NULL); } if(rv != RV_OK) { printf("RvSipCallLegAuthProceed fail. Status is %d.", rv); } } /*=========================================================================================*/ Sample Code The following code demonstrates the implementation of the RvSipCallLegAuthCompletedEv callback function.
Server Authentication Implementation printf("Error in RespondUnauthenticatedDigest"); } } else { /*-----------------------------------------------------------------------------------The authentication procedure was completed with success. Accepts the Invite request.
Server Authentication Implementation Sample Code The following code demonstrates the usage of the authenticator functions for server authentication.
Server Authentication Implementation else { printf("credentials were not verified! n"); } return stat; } /*=========================================================================================*/ 210 HP-UX C SIP Stack Programmer’s Guide
11 WORKING WITH TRANSMITTERS INTRODUCTION The SIP Stack uses transmitter objects (transmitters) for message sending. Each transaction holds a single transmitter and uses it to send SIP messages and message retransmissions. The transaction creates its transmitter upon initialization and terminates it only upon destruction. The transmitter is responsible for all message sending activities, including address resolution, Via header handling, and the actual message sending.
Working With Handles TRANSMITTER A transmitter is capable of sending a single SIP message, request or response. The application should supply the message to the transmitter and the transmitter will be responsible for all message sending activities, including address resolution and DNS, connection handling, Via header handling and the actual message sending. A transmitter is a stateful object that can assume any state from a set defined in the Transmitter API.
Transmitter API Outbound Address An address of an outbound proxy that the transmitter should use. The outbound address is used only if the transmitter is sending a Request message. In this case, the transmitter will use the outbound address as a remote address and the Request-URI will be ignored. The outbound address of the transmitter is ignored if the request contains a Route header, or if the RvSipTransmitterSetIgnoreOutboundProxyFlag() function was called.
Transmitter API Via Branch A branch parameter that will be added to the top Via header of an outgoing Request message. The application can set the branch parameter to the transmitter before sending a Request message. When the Request is sent, if the message already has a branch, it will be replaced with the branch set to the transmitter.
Transmitter API Remark: Regardless of the value of this parameter, the transmitter will update the transport and rport parameters of the top Via header. Keep Msg Flag Indicates that the transmitter should not destruct the message immediately after encoding is completed. Before the transmitter sends a message, it first encodes the message to a buffer and then sends the buffer to the remote party. After encoding is completed, the transmitter destructs the message.
Transmitter API The DNS procedure is a-synchronic, and therefore the send function may return with success before the message was actually sent. If you wish the transmitter to fix the top Via header of the message according to the remote party address and transport types, you should first call the RvSipTransmitterSetFixViaFlag() function. Otherwise the transmitter will only fix the via transport and will add the rport parameter in case it was configured to the SIP Stack.
Transmitter API RvSipTransmitterTerminate() Terminates a transmitter and frees all transmitter-allocated resources. The transmitter will assume the TERMINATED state. Remark: The application is responsible for terminating the transmitter. The SIP Stack will never terminate transmitters that were created by the application. In case of an a-synchronic failure, the transmitter will move to the MSG_SEND_FAILURE with a reason that indicates the nature of this failure.
Transmitter State Machine TRANSMITTER STATE MACHINE The Transmitter state machine illustrated in Figure 11-1 represents the state of the transmitter in the message sending activity.
Transmitter State Machine The RvSipTransmitterStateChangedEv() callback reports transmitter state changes and state change reasons. The state change reason indicates the reason for the new state of the transmitter. The transmitter associates with the following states: RVSIP_TRANSMITTER_STATE_UNDEFINED Indicates that the transmitter was not yet initialized. RVSIP_TRANSMITTER_STATE_IDLE The initial state of the transmitter. Upon transmitter creation, the transmitter assumes the IDLE state.
Transmitter State Machine RVSIP_TRANSMITTER_STATE_ON_HOLD The transmitter assumes the ON_HOLD state if the RvSipTransmitterHoldSending() function is called in the FINAL_DEST_RESOLVED state. The application should call this function if it wishes to manipulate the transmitter destination address and DNS list before the message is sent.
Transmitter State Machine RVSIP_TRANSMITTER_STATE_MSG_SENT Indicates that the message was sent successfully to the remote party. This state does not supply the message. The message is most likely destructed when this state is reached. This state is also an indication that the application should now terminate the transmitter that has completed all its tasks and cannot be used any longer.
Sending Buffers with Transmitter Objects RVSIP_TRANSMITTER_STATE_TERMINATED This is the final state of the transmitter. When a transmitter is terminated, the transmitter assumes the TERMINATED state. Upon reaching the TERMINATED state, you can no longer reference the transmitter. SENDING BUFFERS WITH TRANSMITTER OBJECTS A transmitter can be used for sending a non-SIP message to a specified destination.
Transmitter Manager API RvSipTransmitterMgrCreateTransmitter() IDLE RvSipTransmitterSendBuffer() Failure Success NEW CONN IN USE MSG SEND FAILURE MSG SENT RvSipTransmitterTerminate() RvSipTransmitterTerminate() TERMINATED Figure 11-2 TRANSMITTER MANAGER API Transmitter State Machine when Sending a Buffer The TransmitterMgr controls the SIP Stack collection of transmitters. You use the Transmitter Manager API to create new transmitters.
Transmitter Manager API Sample Code The following code samples describe how to create a transmitter and how to send a message using a transmitter. To create a transmitter 1. Define the event handler functions. 2. Declare a handle for the new transmitter. 3. Set the event handlers in the event handler functions. 4. Call the RvSipTransmitterMgrCreateTransmitter() function and supply the event handlers.
Transmitter Manager API /*========================================================*/ void RVCALLCONV AppTrxStateChangedEv( IN RvSipTransmitterHandle hTrx, IN RvSipAppTransmitterHandle hAppTrx, IN RvSipTransmitterState eState, IN RvSipTransmitterReason eReason, IN RvSipMsgHandle hMsg, IN void* pExtraInfo) { switch (eState) { case RVSIP_TRANSMITTER_STATE_MSG_SENT: case RVSIP_TRANSMITTER_STATE_MSG_SEND_FAILURE: RvSipTransmitterTerminate(hTrx); break; default: break; } } /*========================
Transmitter Manager API Sample Code The following sample demonstrates how to create a new transmitter (steps 2-4). /*=================================================================*/ RvSipTransmitterHandle AppTrxCreate(RvSipTransmitterMgrHandle hTrxMgr) { RvStatus rv = RV_OK; RvSipTransmitterHandle hTrx = NULL; /*Initializing the event handler structure*/ RvSipTransmitterEvHandlers trxEvHandlers; memset(&trxEvHandlers,0,sizeof(RvSipTransmitterEvHandlers)); trxEvHandlers.
Transmitter Manager API Sample Code The following sample demonstrates how to send a message with a transmitter.
Transmitter Manager API 228 HP-UX C SIP Stack Programmer’s Guide
12 EVENT NOTIFICATION INTRODUCTION The Event Notification feature, as defined in RFC 3265, provides an extensible framework by which SIP nodes can request notification from remote nodes indicating that certain events have occurred. The concept behind the Event Notification feature is that entities in the network can subscribe to several resources and/or call states. Each resource and/or call state updates the entity subscribed to it with the states of the specific event.
Typical Message Flow TYPICAL MESSAGE FLOW Figure 12-1 demonstrates a typical flow of messages in a subscription. Notifier Subscriber 1.SUBSCRIBE Expires:100 SUBSCRIBE 2. 200 Expires:80 3. Notify (active) 200 4. Notify (active) Event Notification 200 5. SUBSCRIBE (refresh) Expires:50 REFRESH 200 Expires:50 6. Notify (active) 200 7. SUBSCRIBE (unsubscribe) Expires:0 UNSUBSCRIBE 200 8. Notify (terminated) 200 Figure 12-1 1.
SIP Stack Event Notification Feature request must include an Expires header that determines the duration of the subscription. SIP STACK EVENT NOTIFICATION FEATURE 2. The Notifier acknowledges the subscription with a 200 response. It can shorten the subscription expiration by setting a lower value to the Expires header. 3.
SIP Stack Event Notification Feature Since the application is aware of the resource state it is under, its responsibility is to initiate the NOTFIY messages in all situations. The SIP Stack does not send Notify messages automatically. For example, after accepting a SUBSCRIBE request, the application must immediately send a NOTIFY request.
Working with Handles Call-leg Manager Call-leg (dialog) Subscription List Figure 12-2 WORKING WITH HANDLES Subscription Manager Subscription hCallLeg Subscription hCallLeg Notification List Notification List Notification Notification hTransaction hTransaction Notification Notification hTransaction hTransaction Relationship of Objects All subscriptions and the SubscriptionMgr are identified using handles. You must supply these handles when using the Subscription API.
Subscription Manager API RvSipNotifyHandle defines a notification handle. For an outgoing notification, you receive the notification handle from RvSipSubsNotiferCreate(). For an incoming notification, you receive the notification handle from the RvSipSubsNotifyCreatedEv() callback. SUBSCRIPTION MANAGER API The SubscriptionMgr controls the SIP Stack collection of subscriptions. You use the Subscription Manager API to register application callbacks with the SIP Stack and to create new subscriptions.
Subscription API Expires Header Defines the lifetime of the subscription. Before sending an initial SUBSCRIBE request, you may set the Expires header value for the subscription. The expires value must be smaller than RVSIP_SUBS_EXPIRES_VAL_LIMIT value (4000000). This value will be set in the SUBSCRIBE request as the requested expiration time. The notifier, however, may shorten the expiration value by setting an Expires header with a lower value in the 2xx response.
Subscription API As in a call-leg, you can either set the Call-ID of the dialog, or the SIP Stack will generate the Call-ID. The dialog automatically handles the CSeq, which is increased by one for every outgoing request. Note You must not use the Call-leg Control API with the dialog handle if the subscription was created independently (not related to a connected call-leg). Received Message The last SUBSCRIBE message (Request or Response) that was received by the subscription.
Subscription API State Indicates the state of the subscription setup between two SIP User Agents. You can only access the state parameter with a Get function and it is not modifiable. Subscription Type Indicates whether the subscription represents the subscriber or notifier side of the subscription. You can only access the type parameter with a Get function and it is not modifiable. Event Package Type The type of event package of a subscription.
Subscription API RvSipSubsInitStr() After creating a subscription, you can use this function to set the To, From and Event headers value in a string format, and the Expires header value in the subscription. If the subscription was created within an existing call-leg, you should not set the To and From parameters. RvSipSubsDialogInit() After creating a subscription, you can use this function to set the To, From, Local and Remote Contact parameters of the subscription’s dialog.
Subscription API RvSipSubsUnsubscribe(). It generates and sends a SUBSCRIBE message with an “Expires:0” header, and updates the Subscription state machine to progress to the SUBS_UNSUBSCRIBING state. Note After receiving a successful UNSUBSCRIBE request, your application should wait for a final NOTIFY message. RvSipSubsRespondAccept() When the notifier receives a SUBSCRIBE request, it can accept the request with this function.
Subscription API RvSipSubsTerminate() Causes an immediate shut-down of the subscription, without sending any messages (UNSUBSCRIBE or NOTIFY). The subscription will assume the TERMINATED state. Calling this function causes an abnormal termination of the subscription. All notifications related to the subscription will also be terminated. RvSipSubsAutoRefresh() Sets or unsets the Auto-refresh option in a subscription (Sets it to on or off).
Notification Control API RvSipSubsUpdateSubscriptionTimer() Sets the subscription timer. Calling this function will activate the subscription timer again after it expired. NOTIFICATION CONTROL API The following API functions provide notification control: RvSipSubsCreateNotify() After a subscription was established successfully, you can use this function to create a Notify object in this subscription.
Notification Control API You can call RvSipNotifyGetOutboundMsg() before you call the Notification Control API functions that send a message. You should use this function to add event status information to the message before it is sent. Notify SubsState The value of the Subscription-State header that was set to the NOTIFY request of this Notify object. Stack Instance The handle to the SIP Stack instance to which this Notify object belongs.
Notification Control API RvSipSubsExpirationAlertEv() Alerts the application that the subscription timer is about to expire. The application should use this callback to send a refresh SUBSCRIBE request. The time interval before expiration for this callback to be called is set with the “SubscriptionAlertTime” configuration parameter or with the RvSipSubsSetAlertTimer() function for a specific subscription. Note This event function will not be called when working in Auto-refresh mode.
Subscription State Machine This event notifies both subscriber and notifier applications about the termination of the notification. RvSipSubsFinalDestResolvedEv() Notifies the application that the subscription is about to send a message after the destination address was resolved. SUBSCRIPTION STATE MACHINE The Subscription state machine represents the state of the subscription establishment between two SIP User Agents.
Subscription State Machine RVSIP_SUBS_STATE_UNAUTHENTICATED A subscription in the SUBS_SENT state may receive a 401 or 407 response. In this case, the subscription assumes the UNAUTHENTICATED state. At this point, you can re-send your request with authentication information by calling the RvSipSubsSubscribe() function again. You can also terminate the call using the RvSipSubsTerminate() function.
Subscription State Machine RVSIP_SUBS_STATE_ACTIVATED When a notifier subscription wants to move from PENDING state to ACTIVE state, it sends a NOTIFY request with a “Subscription-State:active” header in it. When sending the request, the subscription assumes the ACTIVATED state. When the notifier receives a 2xx response for this NOTIFY request, the subscription assumes the ACTIVE state. If the notifier receives a non-2xx response for this NOTIFY request, it remains in the ACTIVATED state.
Subscription State Machine RVSIP_SUBS_STATE_UNSUBSCRIBING A subscriber subscription can call the RvSipSubsUnsubscribe() function to send an UNSUBSCRIBE request. After sending the UNSUBSCRIBE, the subscription enters the UNSUBSCRIBING state. The subscription remains in this state until it receives a final response from the notifier. If a 2xx class response is received, the subscription assumes the UNSUBSCRIBE_2XX_RCVD state, while waiting for the NOTIFY request that terminates the subscription.
Subscription State Machine RVSIP_SUBS_STATE_TERMINATING When a notifier subscription sends a NOTIFY request with a “SubscriptionState: terminated” header in it, the subscription assumes the TERMINATING state. When the notifier receives the 2xx response for this NOTIFY request, the subscription assumes the TERMINATED state. If the notifier receives a non2xx response for this NOTIFY request, it remains in the TERMINATING state. RVSIP_SUBS_STATE_TERMINATED This state is the final subscription state.
Subscription State Machine SUBSCRIBER STATE MACHINE SUBS IDLE SUBS REDIRECTED Subscribe()/ Send SUBSCRIBE (user command) 3xx rcvd Subscribe() Send SUBSCRIBE (user command) Notify(active or pending) rcvd/ send 200 SUBS SENT 401/407rcvd SUBS UNAUTH Subscribe() Send SUBSCRIBE (user command) 2xx rcvd / Set noNotify timer SUBS 2xx RCVD 4xx-6x x rcvd or timeout NoNotify timer expired SUBS NOTIFY RCVD Notify(pending) rcvd/ send 200 release noNotify timer 200 rcvd Notify(active) rcvd/ send 200 rel
Subscription State Machine Table 12-1 shows how the state changes after receiving a reject on UNSUBSCRIBE. Table 12-1 State Changes State before Sending UNSUBSCRIBE Request State after receiving Reject on UNSUBSCRIBE Request SUBS_ACTIVE SUBS_ACTIVE SUBS_PENDING SUBS_PENDING SUBS_2XX_RCVD 1. SUBS_2XX_RCVD Reason for Behavior No NOTIFY with “active” as the Subscription-State header value was received and accepted while the state was unsubscribing. 2.
Subscription State Machine NOTIFIER STATE MACHINE SUBS IDLE SUBSCRIBE rcvd SUBS RCVD SubsRespondAccept()/ send 200 SubsRespondPending()/ Send 202 Send Notify(pending) SUBS PENDING send Notify(active) (user command) Send Notify(terminated) (user command) SubsRespondReject()/ send 3xx-6xx refresh rcvd 2xx rcvd on Notify(active) Notify timeout or SubsTerminate() SubsAccept() update timer or SubsReject() SendNotify(terminated)/ user command SUBS TERMINATING SendNotify(terminated) (user command) UNSU
Subscription State Machine Table 12-2 shows how the state changes after rejecting an UNSUBSCRIBE request. Table 12-2 State Changes State that Received UNSUBSCRIBE Request State after Sending Reject on UNSUBSCRIBE SUBS_ACTIVE SUBS_ACTIVE SUBS_PENDING SUBS_PENDING SUBS_REFRESH_RCVD SUBS_ACTIVE Refresh was rejected with 400 when UNSUBSCRIBE was received. SUBS_ACTIVATED 1. SUBS_ACTIVATED No 2xx on NOTIFY with Reason for Behavior “active” as the SubscriptionState header value was received yet.
Subscription State Machine Subscriber Application Subscriber Stack Notifier Stack Notifier Application Create Notify Notify Send NOTIFY NotifyCreatedEv() NotifyEv(NOTIFY_RCVD) NotifyAccept (*) 200(*) NotifyEv(2XX_RCVD(*)) NotifyEv(TERMINATED) NotifyEv(TERMINATED) * This flow is also accurate for any non-2xx on NOTIFY, except 503. NotifyEv indicates the correct staus according to the response code.
Subscription State Machine Subscriber Application Notifier Stack Subscriber Stack Notifier Application Create Notify Notify Send NOTIFY 503 NotifyEv(MSG_SEND_FAILURE) DNS Continue DNS reSend NOTIFY NotifyCreatedEv() NotifyEv(REQ_RCVD) Notify Accept 200 NotifyEv(2xx_RCVD) NotifyEv(TERMINATED) NotifyEv(TERMINATED) Figure 12-6 NOTIFY STATUS NOTIFY Request Failure Notify status represents the status of the notification.
Subscription State Machine RVSIP_SUBS_NOTIFY_STATUS_UNAUTHENTICATED Upon receipt of a 401/407 response to a NOTIFY request, the notification informs the UNAUTHENTICATED status. At this stage, the application may get needed information from the response message. After this stage, the notification is terminated and informs the TERMINATED status. RVSIP_SUBS_NOTIFY_STATUS_REJECT_RCVD Upon receipt of a non-2xx response to a NOTIFY request, the notification informs the REJECT_RCVD status.
Exchanging Handles with the Application RVSIP_SUBS_NOTIFY_STATUS_REQUEST_SENT Upon sending a NOTIFY request, the notification informs the application of the Request-Sent status. At this stage, the notification waits for a response. RVSIP_SUBS_NOTIFY_STATUS_FINAL_RESPONSE_SENT Upon sending a NOTIFY response, the notification informs the application of the Final-Response-Sent status. After this, the notification is terminated and the application is informed of the Terminated status.
Sending a Notification RvChar *strFrom = "sip:user1@172.20.0.1:5060"; RvChar *strTo = "sip:user2@172.20.10.11:5060"; RvChar *strEvent = "hp.event; id=222"; RvInt32 expiresVal = 3000; RvStatus rv; /*-------------------------Creates a new subscription.
Sending a Notification 1. Declare a handle for the new notification and for the NOTIFY request message. 2. Call RvSipSubsCreateNotify(). This function enables you to exchange handles with the SIP Stack. 3. Call RvSipNotifyGetOutboundMsg() to get the NOTIFY message. 4. Set the Subscription-State header in the message. 5. Set the event status information in the message. 6. Call RvSipNotifySend(). This function sends the NOTIFY request to the remote party.
Out-of-Band Subscription RvSipNotifySetSubscriptionStateParams(hNotify, eSubsState, eReason, UNDEFINED); /*-----------------------------------------------Gets the outbound NOTIFY request message, in order to set the status information to it. --------------------------------------------------*/ rv = RvSipNotifyGetOutboundMsg(hNotify, &hNotifyMsg); if(rv != RV_OK) { printf("Failed to get notify outbound message"); return rv; } /*Sets status information in the notify request message...
Out-of-Band Subscription An out-of-band subscription in a call-leg gets its dialog information from the call-leg. For an independent out-of-band subscription, the application should set all necessary dialog parameters (such as Call-ID, To header with tag, and From header with tag). Note You must set the Call-ID parameter of an independent out-of-band- subscription before you call the subscription initialization function (RvSipSubsInit()).
Out-of-Band Subscription SUBSCRIBER OUT-OFBAND SUBSCRIPTION STATE MACHINE CreateOutOfBandSubscription(Subscriber) set Event header Notify(active) rcvd/ send respond SUBS ACTIVE Notify(terminated) rcvd/ send 200 SUBS TERMINATED Figure 12-8 Subscriber Out-of-Band State Machine Note The subscription expiration timer is not set to an out-of-band subscription.
Out-of-Band Subscription /*=========================================================================================*/ void AppCreateOutOfBandSubscription( RvSipSubsMgrHandle hSubsMgr, RvSipCallLegHandle hCallLeg, RvSipSubscriptionType eSubsType, RvChar* strEvent) { RvSipSubsHandle hSubs; RvStatus rv; RvSipEventHeaderHandle hEvent; /*----------------------------------Creates an out-of-band subscription.
Out-of-Band Subscription printf("RvSipSubsSetEventHeader failed "); return ; } /*-----------------------------------------------If notifier--creates and sends notification as usual.
Support for Subscription Forking SUPPORT FOR SUBSCRIPTION FORKING According to the proxying rules in RFC 3261, a SUBSCRIBE request will receive only one 200-class response. The subscription, however, may have been accepted by multiple nodes due to forking. Therefore, the subscriber must be prepared to receive NOTIFY requests from multiple notifiers, with From tags that differ from the To tag received in the SUBSCRIBE 200 response.
Support for Subscription Forking Subscriber Proxy Notifier A Notifier B Subscription A (original) From tag: Y To tag: None SUBSCRIBE From tag: Y SUBSCRIBE From tag: Y SUBSCRIBE From tag: Y 200 OK From tag: Y To tag: U 200 OK From tag: Y To tag: U 200 OK From tag: Y To tag: W Subscription B (forked) From tag: Y To tag: U Discard NOTIFY (active) From tag: U To tag: Y NOTIFY (active) From tag: W To tag: Y NOTIFY (active) From tag: U To tag: Y NOTIFY (active) From tag: W To tag: Y Subscription B (f
Support for Subscription Forking SUBSCRIPTION FORKING EVENTS The Subscription API includes the following event for forking-support implementation. RvSipSubsCreatedDueToForkingEv() A NOTIFY request that is received as a result of SUBSCRIBE sending may create a forked subscription. This event informs the user of the creation of a new forked subscription, and exchanges handle with the application.
Support for Subscription Forking SUBSCRIPTION FORKING CALL FLOW The following call flows illustrate three types of subscription forking. Figure 12-10 illustrates subscription forking that is enabled in the SIP Stack and in the original subscription. Stack Network User NOTIFY (From tag does not m atch) Subscription Forking Code Create Forked Subscription with hidden dialog. Set Subscription State to 2XX_RCVD Prepare Expires value: 1. G et Expires from SUBSCRIBE request 2.
Support for Subscription Forking Figure 12-11 illustrates subscription forking that is disabled in the SIP Stack. Stack Network User NOTIFY (From tag does not match) Find No Matching Dialog Existing Code RvSipTransactionCreatedEv() Figure 12-11 Subscription Forking Disabled in SIP Stack Figure 12-12 illustrates subscription forking that is enabled in the SIP Stack and disabled in the original subscription.
Authentication and DNS SUBSCRIPTION FORKING CONFIGURATION The subscription forking configuration parameters are as follows: bEnableSubsForking Enables the subscription forking feature in the SIP Stack. If this parameter is set to RV_FALSE, all NOTIFY requests that do not exactly match an existing subscription will be handled as general transactions. No forked subscriptions will be created.
REFER 270 HP-UX C SIP Stack Programmer’s Guide
13 REFER INTRODUCTION REFER is a SIP method defined by RFC 3515, “The Session Initiation Protocol (SIP) Refer Method”. The REFER method indicates that the recipient of the REFER request should contact a third party using the contact information provided in the REFER request. RFC 3515 provides a mechanism allowing the party that is sending the REFER to be notified of the outcome of the referenced request.
REFER-Subscription API A REFER sent outside the context of a dialog—UA1 can create an independent refer-subscription, and send the REFER to UA2 to establish a session with UA3, without connecting a call with UA2 first. REFERSUBSCRIPTION API The REFER-Subscription API includes a set of functions and function callbacks that are dedicated to REFER implementation. These functions are called the REFER-Subscription API.
REFER-Subscription API RvSipSubsReferInit() Initializes a subscription with the Refer-To and Referred-By headers. To send a REFER Request, you must first create a subscription using the RvSipSubsMgrCreateSubscription() function. If the subscription is not in the context of an existing dialog, you must also initialize the To and From headers of the subscription and optionally initialize its contact addresses using the RvSipSubsDialogInit() function.
REFER-Subscription API created. The newly created call-leg is initialized and ready to contact the referenced party. To issue the INVITE request to the referenced party, you should call RvSipCallLegConnect(). Note The Refer-To address in the incoming REFER request can include a method parameter that will indicate that the referenced party should be contacted with a method other than INVITE. According to the method, the newly created object can be a call-leg, subscription or transaction.
REFER-Subscription API REFERSUBSCRIPTION EVENTS The following callback function was added to the Subscription layer for REFER control: RvSipSubsReferNotifyReadyEv() This event informs the application that it should send a NOTIFY request on a refer-subscription. The callback is called in the following three stages: Immediately after accepting a REFER request. At this point the application should send the initial NOTIFY request. After a provisional response was received from the referenced party.
REFER-Subscription API B A 1 Subscription A Subscription B 2 REFER 3 5 202 4 NOTIFY 8 C B1 Connected Subscription-state:active 6 SIP/2.0 100 trying 7 INVITE 200 200 NOTIFY Subscription-state:terminated 10 9 ACK SIP/2.0 200 Accepted 11 Figure 13-1 200 12 REFER Process Call Flow The following four call-legs are involved in the complete REFER scenario: Call-leg A—the call-leg that sends the REFER request.
REFER-Subscription API RvSipSubsReferInit() function, and sends the REFER message by calling the RvSipSubsRefer() function. After the REFER message is sent, subscription A moves to the SUBS_SENT state. 3. Call-leg B receives the REFER request and creates a new Refer-subscription B to handle this REFER. The new subscription assumes the SUBS_RCVD state. 4. The application decides to accept the REFER and calls the RvSipSubsReferAccept() function on Subscription B.
REFER-Subscription API request. Using the steps described in step 6, the application builds and sends a NOTIFY request to inform the REFER initiator about the result of the reference attempt. This NOTIFY has a “terminated” value in the Subscription-State header. 11. Subscription A receives the NOTIFY request and informs the application by calling the RvSipSubsNotifyEv() callback. The application accepts this NOTIFY.
Implementing REFER-related Application Callbacks Example 3 The “Refer-To:” header identifies that the referee should contact the refer target with a REFER request which will include the “ReferTo:C” header. Example 4 The “Refer-To:” header identifies that the referee should contact the REFER target with an OPTIONS request which will include the “apple:red” header.
Implementing REFER-related Application Callbacks RvSipSubsStateChangedEv() Callback Implementation The following code is an implementation of the Subscription-state changed callback. The sample demonstrates how to respond to an incoming REFER request with 202, and then connect the new call with the Refer-to party. In this sample, if the method parameter in the Refer-To URI indicates a method different than INVITE, the REFER is rejected with a 400 response.
Implementing REFER-related Application Callbacks } /* Accept incoming refer */ rv = RvSipSubsReferAccept(hSubs, NULL, eObjType, &eObjType, (void**)&hCallLeg); if(rv != RV_OK) { printf("Failed to accept the refer request\n"); return; } /* Connect the new call-leg, to the refer-to party */ rv = RvSipCallLegConnect(hCallLeg); if(rv != RV_OK) { printf("Failed to connect the new call\n"); return; } } } /*===================================================================================*/ RvSipSubsReferNotifyR
Implementing REFER-related Application Callbacks RvSipSubscriptionSubstate eSubsState; RvSipSubscriptionReason eNotifyReason; RvInt32 expires = UNDEFINED; RvInt16 notifyResponseCode; RvStatus rv = RV_OK; RvSipNotifyHandle hNotify; switch (eReason) { case RVSIP_SUBS_REFER_NOTIFY_READY_REASON_1XX_RESPONSE_MSG_RCVD: case RVSIP_SUBS_REFER_NOTIFY_READY_REASON_INITIAL_NOTIFY: notifyResponseCode = responseCode; eSubsState = RVSIP_SUBSCRIPTION_SUBSTATE_ACTIVE; expires = 50; break; case RVSIP_SUBS_R
Implementing REFER-related Application Callbacks { printf("Failed to set notify parameters"); return; } rv = RvSipNotifySetReferNotifyBody(hNotify, statusCode); if (RV_OK != rv) { printf("Failed to set notify body"); return; } /*send the notify request*/ rv = RvSipNotifySend(hNotify); if (RV_OK != rv) { printf("Failed to send notify "); return; } } /*=========================================================================================*/ Sending a REFER Request The following sample code demonstrates ho
Implementing REFER-related Application Callbacks ----------------------------*/ rv = RvSipSubsMgrCreateSubscription(hSubsMgr, NULL, NULL, &hReferSubs); if(rv != RV_OK) { printf("Failed to create new refer subscription"); return; } /* Initiate the subscription dialog parameters */ rv = RvSipSubsDialogInitStr(hReferSubs, From, To, NULL, NULL); if(rv != RV_OK) { printf("subscription dialog initialization failed.
14 WORKING WITH THE TRANSPORT LAYER INTRODUCTION The Transport layer is responsible for the actual transmission of requests and responses over network transports. SIP permits the usage of unreliable transports, such as UDP, and reliable transports, such as TCP and TLS (over TCP), using both IPv4 and IPv6 addresses. TCP, TLS and UDP differ in many ways.
Persistent Connection Handling CONNECTION HASH To reuse open connections, client connections (connections opened by the UAC) are inserted into a hash table. The connection hash key consists of the following elements: The connection transport (TCP or TLS) The connection local address (IP and port) The connection remote address (IP and port) Whenever a SIP Stack object needs to send a message using a reliable transport (TCP or TLS), it first queries the connection hash for existing opened connections.
Persistent Connection Handling CONNECTION CAPACITY PERCENT RFC 3261 recommends that connections should be kept open for a period of time after the last message was exchanged over the connection. However, the exact time period to leave the connection open is defined by the implementation. For example a fixed (location-wise) UA using a default outbound proxy can leave the connection open forever, or until the proxy closes it.
Persistent Connection Handling Undefined persistency (RVSIP_TRANSPORT_PERSISTENCY_LEVEL_UNDEFIN ED) Transaction persistency (RVSIP_TRANSPORT_PERSISTENCY_LEVEL_TRANSC) Transaction user persistency (RVSIP_TRANSPORT_PERSISTENCY_LEVEL_TRANSC _USER) UNDEFINED PERSISTENCY When the SIP Stack is configured to use an undefined persistency level, the following two rules apply: SIP Stack objects do not look for suitable connections in the hash before sending a message, and therefore always open new connections for s
Persistent Connection Handling Since a transaction detaches from a connection only before termination, an INVITE message and its ACK sharing the same addresses will be sent on the same connection (when the response is not 2xx). TRANSACTION USER PERSISTENCY A Transaction User (TU) is an object that uses transactions for sending requests. A call-leg, a subscription and a register-client are all Transaction Users.
Persistent Connection Handling /*==========================================================================*/ SIP STACK OBJECT PERSISTENCY APIS AND EVENTS Each of the SIP Stack objects—call-legs, subscriptions, register-clients, transactions and transmitters—offers several API functions to query and change the persistency level of the object, and to query and determine the connection that the object will use. In the following explanations, XXX represents each of the SIP Stack object types.
Persistent Connection Handling The following API function are supplied: RvSipCallLegGetPersistency() Gets the persistency level of call-legs and subscriptions. Note To set the persistency level of a subscriptions, you must first get the Subscription-associated call-leg and then use the Call-leg API. For more information, see the Call-leg Functions chapter in the SIP Stack Reference Guide. RvSipRegClientGetPersistency() Gets the persistency level of reg-client objects.
Persistent Connection Handling RvSipCallLegSetConnection() Sets a connection to call-legs or subscriptions. The call-leg or subscription will set the connection to every client transaction it uses as long as the connection fits the local and remote addresses of the request. when the connection no longer fits, the call-leg or subscription will automatically detach from it.
Working with Connections RvSipTransactionGetConnection() Gets a connection currently used by a transaction. RvSipTransmitterGetConnection() Gets a connection currently used by a transmitter. RVSIPXXXNEWCONNINUSEEV() This callback function notifies the application that the object is now using a new connection. The connection can be a totally new connection or a suitable connection that was found in the hash.
Connection API RvSipTransportConnectionHandle Defines a connection handle. You receive this handle when creating a new client connection using the RvSipTransportMgrCreateConnection() function. Or, you receive it through the RvSipTransportConnectionCreatedEv() callback when the SIP Stack creates a new server connection.
Connection API Is Enabled Indicates whether the connection is currently in the connection hash and therefore can be used by SIP Stack objects. The application can insert and remove a connection from the connection hash. (See the Connection Control Functions chapter). CONNECTION CREATION AND INITIALIZATION The Transport API provide the following functions for creating and initializing new connections: RvSipTransportMgrCreateConnection() Constructs a new un-initialized connection.
Connection API RvSipTransportConnectionConnect() Connects the connection. You can call this function only in the READY state. Calling this function will cause the connection to move to the CONNECTING state. The connection will move to the TCP_CONNECTED state when an indication is received from the network that the connection was successfully connected. RvSipTransportConnectionTerminate() The behavior of this function depends on the connection state.
Connection API RvSipTransportConnectionDetachOwner() Detaches an owner from the supplied connection. If the connection is left with no other owners, it will be closed. If the same owner is attached to a connection more than once, the first matching owner will be removed. After detaching from a connection, you will stop getting connection events and you must no longer use the connection handle.
Connection API RvSipTransportConnectionStatusEv() The connection notifies about events that do not effect the connection state using the connection status callback. If, for example, there was an error in the connection, the connection will notify the application with RVSIP_TRANSPORT_CONN_STATUS_ERROR. The connection will then disconnect with the RVSIP_TRANSPORT_CONN_REASON_ERROR reason. Note You do not have to register to this callback if you do not want to get connection statuses.
Connection API RVSIP_TRANSPORT_CONN_STATE_CONNECTING Calling the RvSipTransportConnectionConnect() function in the READY state will move the connection to the CONNECTING state. While in the CONNECTING state, the SIP Stack tries to connect the connection to the remote party. If the connect attempt succeeds, the connection assumes the TCP_CONNECTED state. Otherwise, the connection assumes the TERMINATED state with the RVSIP_TRANSPORT_CONN_REASON_ERROR reason.
Connection API CLIENT CONNECTION STATE MACHINE Figure 14-1 illustrates the Client Connection state machine.
Connection API Sample Code The following sample code demonstrates how to create an application connection. The application becomes the connection owner and supplies the connection with its event handlers. In this example, the application chooses to register only on the RvSipTransportConnectionStateChangedEv() callback function.
Server Connections } return RV_OK; } /*=========================================================================================*/ When working with calls or subscriptions, a message can be record-routed and the destination can be determined according to the Route list. For more information on initiating a TCP call, see the Working with Call-legs (Dialogs) chapter. Sample Code The following sample code demonstrates an implementation of the RvSipTransportConnectionStateChangedEv() callback function.
Server Connections Generally, server connections should be closed by the party that initiated the connection. It is highly recommended not to terminate server connections from the application to prevent unexpected interruptions in message reception and sending flow. Most server connections are not reusable and are not inserted into the connection hash. (For an exception to this, see Server Connection Reuse.) However, a transaction that uses a server connection becomes the connection owner.
Server Connections RvSipTransportConnectionStateChangedEv() A server connection is a stateful object that can assume different states according to the Connection state machine. Through this callback, you receive notifications of server connection state changes and the associated state change reason. Note This callback signature is identical to the callback used for client connection state changes, and the states used for server connections are a subset of the client connection states.
Server Connections RVSIP_TRANSPORT_CONN_STATE_CLOSED The connection moves to the CLOSED state upon receiving a network event that indicates that the connection was closed by the remote party. In the CLOSED state, the connection closes its internal socket. The connection then moves to the TERMINATED state. RVSIP_TRANSPORT_CONN_STATE_TERMINATED The final connection state. When a connection is terminated, the connection assumes the TERMINATED state.
Server Connections serverConnectionTimeout = –1 The SIP Stack never closes Server connections, which always wait to be closed by the connection initiator. This is also the default behavior of the SIP Stack. serverConnectionTimeout > 0 When the last owner detaches from the connection, a timer with the value of “serverConnectionTimeout” is set. The SIP Stack will close the connection when the timer expires.
Server Connection Reuse { printf(“RvSipTransportConnectionGetRemoteAddress() failed”); *pbDrop = RV_TRUE; } if (portRemote < 5000 || portRemote > 60000) { printf("0x%p incoming connection is DISAPPROVED by Application: remote addr %s:%d, local addr %s:%d", hConn, strIPRemote, portRemote, strIPLocal, portLocal); *pbDrop = RV_TRUE; } return RV_OK; } /*===================================================================*/ SERVER CONNECTION REUSE When using a reliable transport, SIP entities use a connectio
Server Connection Reuse Both the client and the server take part in the connection reuse mechanism. CLIENT SIDE The client opens new connections with the server. The client should indicate to the server if a specific opened connection can be reused by the server for new requests. This indication is carried as a new parameter called “alias” that is added to the Via header of a request sent on this connection. For example: Via: SIP/2.0/TLS 10.54.32.
Server Connection Reuse RvSipHeaderListElemHandle hListElem = NULL; RvStatus rv = RV_OK; RvSipTransport eTransport; if(RvSipMsgGetMsgType(hMsgToSend) == RVSIP_MSG_REQUEST) { /* Get the top Via header. */ hVia = RvSipMsgGetHeaderByType(hMsgToSend, RVSIP_HEADERTYPE_VIA, RVSIP_FIRST_HEADER, &hListElem); /* Get the transport parameter from the top Via header. */ eTransport = RvSipViaHeaderGetTransport(hVia); if(eTransport == RVSIP_TRANSPORT_UDP) { /* No need to set an alias for request over UDP...
Server Connection Reuse SERVER SIDE When the SIP Stack receives a request message on an incoming connection, it checks the Via header and looks for the alias parameter. The alias parameter indicates that the originator of the request wants to create a Transport layer alias. If the alias parameter exists, the SIP Stack consults the application whether this connection is authorized to be reused, using the dedicated callback function, RvSipTransportConnectionServerReuseEv().
Server Connection Reuse Sample Code The following sample code demonstrates an implementation of the RvSipTransportConnectionServerReuseEv() callback function. In this implementation, the application checks the connection authorization (out of the scope of this sample) and if authorized, enables it.
Using TCP Transport The application can use the SIP Stack Transport and Resolver APIs to authorize a connection. You can see an example of connection authorization in the simpleConnectionReuse sample application in the the Sample Applications chapter. USING TCP TRANSPORT RFC 3261 defines the use of TCP transport by using the transport=TCP parameter in a SIP URL address that indicates the destination of the message.
SIP Stack and TLS Phase 1: TCP connection establishment—as stated above, TLS uses TCP as its underlying transport protocol. Therefore, a TLS handshake can start only after a TCP connection has reached the CONNECTED state.
SIP Stack and TLS TLS ENGINE A TLS engine is an entity that binds together several parameters needed for TLS, such as SSL version, engine certificate, trusted root certificates authorities, and so on. In most cases, a TLS engine will be constructed immediately after SIP Stack initialization and will “live” for the entire duration of the SIP Stack’s life. All TLS engines are destructed with the SIP Stack when it is destructed.
SIP Stack and TLS RvSipTransportTlsEngineAddTrustedCA() A TLS engine can trust zero, one or more root certificates. Once an engine trusts a root certificate, it will approve all valid certificates issued by that root certificate. Trusted certificates are (usually) root certificates. You add trusted certificates to an engine by using RvSipTransportTlsEngineAddTrustedCA() after the engine has been constructed.
SIP Stack and TLS unsigned char *keyEnd RvInt privKeyLen = 0; RvChar cert[STRING_SIZE] = {'\0'}; unsigned char *certEnd = cert; RvInt certLen RvSipTransportTlsEngineHandle hTlsServerEngine = privKey; = 0; = NULL; memset(&TlsEngineCfg,0,sizeof(TlsEngineCfg)); /*Loads the key for the server engine.
SIP Stack and TLS /*Uses the initialized configuration to build the server TLS engine*./ rv = RvSipTransportTlsEngineConstruct(g_hTransportMgr, &TlsEngineCfg, sizeof(TlsEngineCfg), &hTlsServerEngine); if (RV_OK != rv) { HandleErrorFunction("failed to construct TLS server engine"); } /*Makes sure that the private key matches the certificate installed on the engine.
SIP Stack and TLS RvSipTransportConnectionTlsGetEncodedCert() Gets the encoded certificate of a connection. RvSipTransportConnectionTlsRenegotiate() Restarts the TLS handshake on the next received message. As a result, the certificate will be renegotiated and the session key will be regenerated. The state of the connection is not affected by the undergoing process of the renegotiation. The application does not receive any indication about renegotiation success.
SIP Stack and TLS RvSipTransportConnectionTlsPostConnectionAssertionEv() As described in the introduction, a TLS attack can be performed in the following manner: computer mallice.com holds the valid certificate of p.com and displays it in the handshake process. The certificate is valid so the handshake will be completed successfully. If this attack is preformed, the user might deliver data to an unauthenticated party.
SIP Stack and TLS RvInt certLen = TLS_CERT_STR_LENGTH; RvStatus rv = RV_OK; RvChar *pszCert = (RvChar*)&szCert; /*Obtains the certificate as string from the certificate object.*/ rv = RvSipTransportTlsEncodeCert(certificate,&certLen,szCert); if (RV_OK != rv) { HandleErrorFunction("failed to get certificate"); } /*Converts the certificate to open SSL format.
SIP Stack and TLS RVSIP_TRANSPORT_CONN_TLS_STATE_UNDEFINED No TLS sequence was initiated on the connection. RVSIP_TRANSPORT_CONN_TLS_STATE_HANDSHAKE_READY The connection is TCP-connected and ready to start the TLS handshake. To move the connection to the TLS_CONNECTED state, call RvSipTransportConnectionTlsHandshak(). RVSIP_TRANSPORT_CONN_TLS_STATE_HANDSHAKE_STARTED The connection started the handshake process.
SIP Stack and TLS TLS CONNECTION STATE MACHINE HANDSHAKE_READY RvSipTransportConnectionTlsHandshak() HANDSHAKE_STARTED TLS hadshake has failed TLS handshake was completed Post connection assertion failed HANDSHAKE_FAILED HANDSHAKE_COMPLETED Connection is asserted or no assertion is needed CONNECTED TLS close request, Close CLOSE_SEQUENSE_STARTED TCP Connection is terminating Figure 14-4 322 HP-UX C SIP Stack Programmer’s Guide TLS Connection State Machine TERMINATED
SIP Stack and TLS Sample Code The following sample code shows how to start a TLS handshake /*=========================================================================================*/ static RvSipTransportTlsEngineHandle g_hTlsServerEngine; RvStatus RVCALLCONV TransportConnectionTlsStateChanged( IN IN RvSipTransportConnectionHandle RvSipTransportConnectionAppHandle hConnection, hAppConnection, IN RvSipTransportConnectionTlsState eState, IN RvSipTransportConnectionStateChangedReason eReason) { R
SIP Stack and TLS numOfTlsEngines The maximum number of TLS engines. TLS engines are used to give a set of properties to a TLS connection. maxTlsSessions The maximum number of TLS sessions. A TLS session is the TLS equivalent to a TCP connection and contains TLS data required to manage the TLS connection. For more information see the Configuration chapter.
Working with IPv6 Addresses pritf("Connection 0x%x: remote multihoming address %s was %s", hConn, pAddrInfo->address.strIP, } break; default: printf("Connection 0x%x: status %d was reported", hConn, eStatus); } return; } /*===============================================================*/ In some standards, the primary address is referred to as a path. Paths can be changed by peers at any moment after the connection was established.
Working with IPv6 Addresses 2001:2353:0000:0000:0000::1428:57ab 2001:2353:0:0:0:0:1428:57ab 2001:2353:0::0:1428:57ab 2001:2353::1428:57ab However, 2001::25de::cade is invalid. Also, leading zeros in all groups can be omitted, thus 2001:2353:02de::0e13 is the same as 2001:2353:2de::e13. If the address is an IPv4 address in disguise, the last 32 bits may be written in decimal. Thus, ::ffff:192.168.89.9 is the same as ::ffff:c0a8:5909, but not the same as ::192.168.89.9 or ::c0a8:5909.
Transport Layer Raw Buffer and Message Monitoring IPV6 ADDRESSES AND THE TRANSPORT ADDRESS STRUCTURE Several SIP Stack API functions receive a structure pointer of the RvSipTransportAddr type as an input parameter. If you want to set an IPv6 address to a RvSipTransportAddr structure, follow these steps: 1. Create a string that corresponds to an IPv6 address (such as fec0::1234:123). 2. Set the string to the strIP member of the structure. 3. Set a scope ID to the Ipv6Scope member of the structure. 4.
Transport Layer Raw Buffer and Message Monitoring RvSipTransportBufferReceivedEv() Just before parsing an incoming SIP message the SIP Stack gives the application the chance to look at the message raw buffer. The callback supplies a buffer with exactly one textual SIP message, the local and remote addresses of the message, and the connection handle if TCP was used. Based on the callback information, the application can instruct the SIP Stack to discard the buffer using an OUT parameter.
15 WORKING WITH DNS INTRODUCTION SIP uses DNS procedures to allow a client to resolve a SIP Uniform Resource Identifier (URI) into the IP address, port, and transport protocol of the next hop to contact. The SIP Stack DNS feature is implemented in the Resolver and Transmitter layers of the SIP Stack and propagates upwards to all layers. The DNS queries that the SIP Stack performs are non-blocking.
Introduction A list of domain suffixes—tells the SIP Stack which domain suffixes should be appended to FQDNs. (For example, “hp.com” is the suffix for the “host1.hp.com” host.) Using suffixes allows using a short version of a name that is within the suffix domain. The SIP Stack supports three ways of obtaining the information that is required. The information can be provided using the RvSipStackCfg configuration structure when initializing the SIP Stack.
SIP Stack Implementation ROOT/NAPTR SRV (SIP) SRV (SIP) A A H1 H2 Figure 15-1 H3 SRV (SIP) A H4 H5 AAAA H6 H7 H8 A DNS/SRV Spanned Tree DNS/ENUM RECORD RFC 3824 specifies the usage of ENUM NAPTR records for relating between E.164 numbers and URIs. For more information on ENUM, see the Advanced Features chapter. SIP STACK IMPLEMENTATION Before sending a request, the transaction obtains the destination host name from the request message.
SIP Stack Implementation IP addresses list—the result of an A/AAAA query applied on the first element of the Host list. After the A/AAAA query is made, the first element in the Host list is moved to the used host element member of the DNS list. In addition, the DNS List object holds the host record used to resolve the IP and the SRV record used to resolve the port. Note that the SRV list, Host list and used SRV are only kept if the SIP Stack was compiled with the Enhanced DNS feature.
SIP Stack Implementation When an ENUM query returns as a result of a valid URI, the Stack tries to resolve this URI automatically, using the general URI resolution methodology. During URI resolution, the following algorithm is used for filling the DNS list object. For each element (such as, host, IP): 1. Remove (pop) the element from the list. 2. Query the DNS for that element, and insert the results into the DNS list. 3. Repeat steps 1 and 2 for the next sub-list until the IP sub-list is filled.
State Machine and API Functions STATE MACHINE AND API FUNCTIONS In general, whenever a message send has failed, the transaction moves to a new state that indicates that failure, RVSIP_TRANSC_STATE_CLIENT_MSG_SEND_FAILURE. In the state change callback, the reason that is attached to the state indicates the reason of the failure. The reason can be one of the following: RVSIP_TRANSC_REASON_TIME_OUT A transaction has timed out. (For example, an INVITE did not get a final response.
State Machine and API Functions RvSipTransactionDNSContinue() will not terminate the original transaction. The application must send ACK on the original transaction by calling the RvSipTransactionAck() function. Note The application must first call RvSipTransactionDNSContinue() to copy the transaction and then call RvSipTransactionAck() to trigger an ACK on the original transaction.
State Machine and API Functions switch(eNewState) { case RVSIP_TRANSC_STATE_CLIENT_MSG_SEND_FAILURE: { /*Creates a new "cloned" transaction.*/ rv= RvSipTransactionDNSContinue(hTransaction, (RvSipTranscOwnerHandle)NULL, &hCloneTransc); if(rv != RV_OK) { /*Performs the error handle routine.
Manipulating the DNS List Object MANIPULATING THE DNS LIST OBJECT After calling the RvSipTransactionDnsContinue() function, the application receives a handle to the new cloned transaction. By calling the RvSipTransactionDNSGetList() function, the application can get the handle to the DNS List object (RvSipTransportDNSListHandle) and manipulate the list. By manipulating the DNS list, the application can: Add records taken from internal source, rather than retrieved from an external DNS server.
Manipulating the DNS List Object RvSipTransportDNSListGetXXXXElement() RvSipTransportDNSListRemoveTopmostXXXXElement() RvSipTransportDNSListPopXXXXElement() RvSipTransportDNSListPushXXXXElement() The insertion and extraction of records to and from the lists is done using the following structures: RvSipTransportDNSSRVElement For SRV elements. RvSipTransportDNSHostNameElement For hosts elements. RvSipTransportDNSIPElement For IP elements.
Manipulating the DNS List Object /*=========================================================================================*/ RvStatus ReplaceTopMostIp(IN RvSipTranscHandle hTransaction, IN RvSipTransportMgrHandle hTransportMgr) { RvStatus rv = RV_OK; RvSipTransportDNSListHandle hDnsList = NULL; RvChar strIP="172.3.4.45"; RvSipTransportDNSIPElement element; /*Obtains the DNS list from the transaction.
DNS Support for Call-legs, Subscriptions, and Register-Clients return rv; } } /*=========================================================================================*/ DNS SUPPORT FOR CALL-LEGS, SUBSCRIPTIONS, AND REGISTERCLIENTS As mentioned above, DNS support propagates upwards to objects that use the Transaction layer.
DNS Caching REGISTER-CLIENT LAYER The RVSIP_REG_CLIENT_STATE_MSG_SEND_FAILURE state indicates a message send failure. The application can obtain the DNS List object handle by calling the RvSipRegClientDNSGetList() function. Once the application has a handle to the list, it can manipulate the list using the Transport API. REGISTER- CLIENT DNS API Calling the RvSipRegClientDNSContinue() function causes the SIP Stack to prepare an internal cloned transaction and terminate the original transaction.
DNS Caching DNS CACHING COMPILATION FLAGS Several compilation flags are used to configure the DNS caching feature. All the compilation flags are located in the common/config/rvusrconfig.h file and are described below: RV_DNS_USES_CACHING To enable caching, the RV_DNS_USES_CACHING compile time constant should be set to RV_YES. RV_DNS_CACHE_HASH_SIZE Cache lookup is implemented using static open hashing. The size of hash table is given by the compile time constant, RV_DNS_CACHE_HASH_SIZE.
16 WORKING WITH RESOLVERS INTRODUCTION The SIP Stack uses resolvers to produce data that is related to DNS. A resolver object (resolver) is responsible for retrieving a piece of DNS information. In some cases this information can be obtained by a single DNS query (such as NAPTR resolution), in other cases several queries are required (such as host resolution when the network type, , is unknown).
Resolver Entities RVSIP_RESOLVER_MODE_UNDEFINED Represents no-resolution mode. RVSIP_RESOLVER_MODE_FIND_TRANSPORT_BY_NAPTR Instructs the resolver to try obtaining NAPTR records for a domain. The resolver will use the protocol field of the NAPTR record to determine the transport, for example, getting the available transports for hp.com. The result will be a list of SRV record pointers.
Working with Handles RVSIP_RESOLVER_MODE_FIND_URI_BY_NAPTR Gets the NAPTR record for an ENUM record in a DNS server. For example, trying to resolve a phone number, such as +97237679623, will result in an NAPTR query, for 3.2.6.9.7.6.7.3.2.7.9.e164.arpa..The result of this kind of query will be a regular expression. RESOLVER MANAGER The ResolverMgr manages the collection of resolvers and is mainly used for creating new resolvers.
Resolver API RESOLVER CALLBACKS The application has to specify an RvSipResolverReportDataEv() callback when activating the resolver (by calling RvSipResolverResolve()). This callback will pop whenever the DNS algorithm session has ended, and will indicate if the algorithm session was successful or not. After the callback has popped, the DNS list that you supplied the resolver should contain the answers. You can obtain the list by using the RvSipResolverGetDnsList() function.
Resolver API domain list is set according to the configuration of the computer and is managed by the ResolverMgr. The application can use the RvSipResolverMgrSetDnsDomains() function to provide a new set of DNS domains to the SIP Stack. It can use the RvSipResolverMgrGetDnsDomains() function to get the current list of DNS domains. Sample Code The following sample code illustrates the use of a resolver with a DNS list.
Resolver API void ResolveHostToIp() { RvStatus rv = RV_OK; RvSipResolverHandle hStackResolver = NULL; RvSipTransportDNSListHandle hDNSlist; /* 1. Building a DNS list*/ rv = RvSipTransportDNSListConstruct(hTransportMgr,hPool,10,&hDNSlist); if (RV_OK != rv) HandleError(); /* 2. Creating a resolver */ rv = RvSipResolverMgrCreateResolver(hResolverMgr,(RvSipAppResolverHandle)NULL, &hStackResolver); if (RV_OK != rv) HandleError(); /* 3. Trying to resolve the host "host.
17 SIP STACK LOG INTRODUCTION The SIP Stack includes a logging module that produces output for debugging, monitoring and tracking of the activity of applications built with the SIP Stack. The Log output provides detailed information important for application development and ongoing system maintenance. Suggestions for using the Log include: Post Mortem Monitoring If you want to know the full history of calls over your network, use the Log output to monitor all network events related to the SIP Stack.
Source Identifiers SOURCE IDENTIFIERS The Log uses various source identifiers for monitoring SIP Stack behavior. You can set up the Log to analyze any of the source identifiers and specify the level of logging required for each one independently. Table 17-1 shows the main source identifiers that the Log analyzes: Table 17-1 Source Identifiers Analyzed by the Log Source Identifiers Description CALL Call-leg related operations. AUTHENTICATOR Authenticator related operations.
Log Configuration WARN—warning about a possible non-fatal error. ERROR—indicates that a non-fatal error has occurred, such as faulty application behavior, insufficient allocations or illegal network activity. EXCEP—indicates that a fatal error has occurred that prevents the SIP Stack from continuing to operate. LOCKDBG—debug information about locking activities in the different modules of the SIP Stack. If your application is not multithreaded it is recommended not to use LOCKDBG messages.
Log Configuration After setting the log level to the above groups of source identifiers, the StackMgr will check if any of the specific sources was set to a non-zero log level. If so, this level will be set for the specific source overriding the default log level. The RvSipLogFilters enumeration contains a filter for each of the log message types.
Message Structure RvSipStackCfg stackCfg; RvSipStackInitCfg(sizeof(stackCfg), &stackCfg); stackCfg.defaultLogFilters = RVSIP_LOG_INFO_FILTER | RVSIP_LOG_DEBUG_FILTER | RVSIP_LOG_ERROR_FILTER | RVSIP_LOG_WARN_FILTER | RVSIP_LOG_EXCEP_FILTER; /*==========================================================================*/ MESSAGE STRUCTURE The default Log contains rows of messages.
Controlling the Log /*==========================================================================*/ RvSipStackCfg stackCfg; RvSipStackHandle hStack; RvStatus AppInitSipStack() { FILE *logFile; RvSipStackInitCfg(sizeof(stackCfg), &stackCfg)); /*Open the log file for writing*/ logFile = fopen("MyLog.txt","w"); /*Register the log function in the configuration structure*/ stackCfg.pfnPrintLogEntryEvHandler = AppLogPrintFunction; /*Save the file pointer as a log context (optional)*/ stackCfg.
Compilation Log Control fwrite(data, strlen(data), 1, logFile); fflush(logFile); } /*==================================================================================*/ Note When you replace the default logging, the formatted text includes only the message type, source identifier, and log message. COMPILATION LOG CONTROL The application can control the compiled log messages by setting the “RV_LOGMASK” compilation flag found in the rvusrconfig.
Compilation Log Control 356 HP-UX C SIP Stack Programmer’s Guide
18 MEMORY POOL INTRODUCTION The SIP Stack does not allocate memory dynamically. All memory is allocated during the initialization process and is managed by the SIP Stack. The memory is divided into blocks called pages. The page size and the number of pages are configurable. The collection of all pages is called a memory pool. The memory pool manages the pages, supplying a simple API that allows the user to receive and recycle memory bytes when needed.
Using the Memory Pool RPOOL_Construct() Constructs a new memory pool. The memory for the new pool is allocated when calling this function. This function receives parameters that indicate the number of pages and the size of each page in the newly constructed pool. RPOOL_Destruct() Destroys a memory pool. Memory allocated to the pool is freed. RPOOL_GetPage() Gets one page from the memory pool. RPOOL_FreePage() Releases a given page. This function returns the released page to the memory pool.
Using the Memory Pool Sample Code /*===========================================================================*/ void AllocatePageExample() { RvStatus retStatus; /*Defines a memory pool handle.*/ HRPOOL appPool; /*Defines a memory page handle.*/ HPAGE appPage; /*Constructs a new memory pool with 10 pages and 20 bytes on each page.
Using the Memory Pool Note You can construct the application memory pool when you initialize your application and keep using the memory pool until the application terminates. COPYING A PAGE INTO A BUFFER The following code demonstrates how to copy the content of a page into a consecutive buffer.
Using the Memory Pool Sample Code /*=========================================================================================*/ RvStatus CopyBuffersWithPage(IN HRPOOL memoryPool, IN HPAGE memoryPage) { RvStatus retStatus; RvInt32 offset, size; RvChar source[50], dest[50]; /*Sets the source buffer.*/ strcpy(source,"Hello, How are you?"); size = strlen(source)+1; /*Copies the source buffer to the page.
Using the Memory Pool 362 HP-UX C SIP Stack Programmer’s Guide
19 ADVANCED FEATURES EXTENSION SUPPORT SIP provides a mechanism for allowing a client to request that a particular protocol extension be used to process a request. The client uses either the Require or Proxy-Require headers to indicate the requested extensions. Extensions are identified using “option-tags,” which are unique string names defined in the extension specifications.
Extension Support does not recognize the option-tag on the Require header, the server responds with a 420 response message and adds an Unsupported header with the unsupported option-tag. For more information, see the Configuration chapter. Sample Code The following code configures the SIP Stack to support two extensions: PRACK—(reliable provisional responses) specified by the 100rel option tag MyExtn—(a proprietary extension) specified by the MyExt option tag.
Extension Support Sample Code The following sample code demonstrates how to identify and reject a request with an unsupported extension when working with the Transaction layer. The request is handled in the context of the transaction state changed callback.
Multihomed Host MULTIHOMED HOST The Multihomed Host feature allows sending and receiving requests from different local IP addresses. This feature can be used to send requests from different network cards or from the same network card with several different ports. This feature also enables the dynamic opening and closing of the local IP addresses, which are used for request sending and reception, at any moment of the SIP Stack life cycle. This sub-feature is called Dynamic Local Addresses (DLA).
Multihomed Host Local IP address as a string Local port When a request is sent, the local address is chosen according to the destination transport and address types. For example, if a request destination is a TCP IPv6 address, the local address to use is also a TCP IPv6 address. Therefore, each of the SIP Stack objects holds several local addresses for each combination of transport and address types.
Multihomed Host DYNAMIC LOCAL ADDRESSES (DLA) The Dynamic Local Addresses (DLA) feature of the SIP Stack enables the application to open and close local IP addresses at runtime. To enable the DLA feature, you have to set the bDLAEnabled configuration parameter to RV_TRUE. By default, the DLA feature is disabled since DLA consumes extra resources such as memory and mutexes.
Multihomed Host rv = RvSipTransportMgrLocalAddressGetFirst(hTransportMgr, RVSIP_TRANSPORT_UDP, &hLocalAddr); if (rv != RV_OK) { if (rv == RV_ERROR_NOT_FOUND) { printf("No UDP address is opened currently in the Stack\n"); } } else { RvSipTransportMgrLocalAddressRemove(hTransportMgr, hLocalAddr); } /* Opens new UDP address */ addrDetails.eAddrType = RVSIP_TRANSPORT_ADDRESS_TYPE_IP; addrDetails.eTransportType = RVSIP_TRANSPORT_UDP; addrDetails.port = 6060; strcpy(addrDetails.strIP,"172.20.4.
High Availability HIGH AVAILABILITY The SIP Stack provides a save and restore mechanism that enables the application to back up calls that have reached the CONNECTED state or subscriptions in the ACTIVE state. Backing up calls and subscriptions lets application developers implement redundancy capabilities in their systems, allowing back-up systems to “take over” when the primary system goes down. Given that media streams remain active, the backup object (call-leg or subscription) will not be affected.
High Availability RvSipSubsStoreActiveSubs—copies all subscription parameters from a given subscription to a given buffer. This buffer should be supplied when restoring the subscription. RvSipSubsRestoreActiveSubs—restores all subscription parameters from a given buffer. The subscription will assume the ACTIVE state. Sample Code The following code replaces a connected call-leg with a newly created call-leg using the store/restore mechanism.
Replaces Header return hNewCallLeg; } /*=====================================================================================*/ REPLACES HEADER The Replaces header is a SIP header defined by draft-ietf-sip-replaces. This header is used to logically replace an existing SIP dialog with a new SIP dialog. The Replaces header contains the Call-ID, To tag and From tag, which identify a dialog to be replaced. The Replaces header may also contain an “early-only” flag.
Replaces Header different Replaces header to be inserted into the INVITE, or that the INVITE will not contain any Replaces header, it can set the Replaces header of the callleg before connecting the call. RECEIVING AN INVITE MESSAGE WITH REPLACES HEADER When an initial INVITE message that contains a Replaces header is received, the call-leg calls the evStateChanged callback with the RVSIP_CALL_LEG_STATE_OFFERING state and the RVSIP_CALL_LEG_REASON_REMOTE_INVITING_REPLACES reason.
Replaces Header Sample Code The following sample code demonstrates the State Changed callback.
Replaces Header break; case RVSIP_CALL_LEG_REPLACES_REASON_FOUND_TERMINATED_DIALOG: responseCode = 603; break; case RVSIP_CALL_LEG_REPLACES_REASON_DIALOG_NOT_FOUND: case RVSIP_CALL_LEG_REPLACES_REASON_FOUND_NON_INVITE_DIALOG: case RVSIP_CALL_LEG_REPLACES_REASON_FOUND_INCOMING_EARLY_DIALOG: default: responseCode = 481; break; } /* Reject the new call-leg.
SIP Session Timer SIP SESSION TIMER The Session Timer extension enables determining the duration time of a call. A Session-Expires header included in the 2xx response of an initial INVITE determines the session duration. Periodic refresh enables extending the duration of the call and allows both User Agents (UAs) and proxies to determine if the SIP session is still active. The refresh of a SIP session is done through a reINVITE or UPDATE.
SIP Session Timer minSE The minimum value for the session interval that the application is willing to accept. If the application does not set this parameter, the minSE value is set to the default value of 90 seconds according to the Session Timer RFC. Also, the Min-SE header will not be present in the sent requests (except for a request, following a 422 response). However, if the application set this parameter to 90 or any other value, the Min-SE header will appear in any sent request.
SIP Session Timer Preference and Negotiation Parameters The preference and negotiation parameters are temporary parameters used before the final session timers parameters were determined. The preference parameters are the parameters that the local party prefers for this session. You can only set the preference parameters. Each setting of preference parameters is valid for a single session timer refresh within a dialog (either an initial or subsequent refresh).
SIP Session Timer If the sessionExpires parameter is set to 0, the Session-Timer mechanism is turned off immediately in the current call-leg. Moreover, the Session-Timer mechanism can be turned on by: Calling this function with non-zero sessionExpires value in the middle of a call. Calling one of the Session-Timer Call-leg API functions for refreshing the current session (RvSipCallLegTranscSessionTimerGeneralRefresh() or RvSipCallLegSessionTimerInviteRefresh()).
SIP Session Timer RvSipCallLegTranscSessionTimerSetPreferenceParams() Sets the preferred Session Timer parameters associated with this transaction. The only general transaction allowed is “UPDATE”. These parameters may not be equal to the Session Timer parameters of the call at the end of the negotiation.
SIP Session Timer RvSipCallLegSessionTimerRefreshAlertEv() Notifies that the alert time (the time in which the application needs to send a reINVITE or UPDATE to refresh the call) is expired. The application needs to send a refresh using the RvSipCallLegSessionTimeRefresh() or RvSipCallLegTranscSessionTimerGeneralRefresh() functions. (This callback is called only on the refresher side).
SIP Session Timer When the callback is called with the RVSIP_CALLLEG_SESSION_TIMER_DEST_NOT_SUPPORTED reason, it notifies the local party that a 2xx final response was received, but the server does not support the Session Timer. The application should return synchronously whether or not it wants to execute Session Timer. The Session Timer mechanism can be operated as long as one of the two UAs in the call leg supports the extension.
SIP Session Timer /*===================================================================================*/ RvStatus RVCALLCONV CallLegSessionTimerRefreshAlertEv( IN RvSipCallLegHandle IN RvSipAppCallLegHandle hAppCallLeg) hCallLeg, { RvStatus status = RV_OK; RvInt32 SE = 500; RvInt32 minSE = 100; /*The local party wishes to be the refresher.*/ RvSipCallLegSessionTimerRefresherPreference eRefreshPref = RVSIP_CALL_LEG_SESSION_TIMER_REFRESHER_LOCAL; /*Sets the session timer parameters.
General URI Scheme Support GENERAL URI SCHEME SUPPORT SIP defines and uses different URI schemes, such as “sip”, “sips”, “im”, “pres” and “tel”. In addition, some implementations define proprietary URI schemes. A general framework in the SIP Stack provides support for sending any type of URI scheme. In each of the SIP Stack layers, a new callback function was added with the following form: RvSipXXXOtherURLAddressFoundEv().
Type of Service (TOS) When working with Other URI support, whenever a SIP Stack object tries to send a request and the destination address scheme is im or pres, the RvSipXXXOtherURLAddressFoundEv() callback will not be called, and the SIP Stack will manage to handle the address. TEL URI EXTENSION SUPPORT The SIP Stack also provides extension support for the “tel” URI scheme.
Type of Service (TOS) RvSipTransportConnectionSetIpTosSockOption() Sets the option value into the local address, from which the outgoing connection is opened. All the packets (TCP) that are sent on this connection will be marked with the set value in the TOS byte of the IP header. This function can be called from RvSipXXXNewConnInUseEv() callback. RvSipTransportConnectionGetIpTosSockOption() Gets the option value that was set for the outgoing connection.
Type of Service (TOS) /*==========================================================================*/ RvStatus SetTOSForAllLocalAddresses( IN RvSipTransportMgrHandle hTransportMgr, IN RvInt32 tos, IN RvSipTransport eTransportType) { RvStatus rv; RvSipTransportLocalAddrHandle hLocalAddr = NULL; rv = RvSipTransportMgrLocalAddressGetFirst( hTransportMgr, eTransportType, &hLocalAddr); if (RV_OK!=rv && RV_ERROR_NOT_FOUND!=rv) { printf("RvSipTransportMgrLocalAddressGetFirst() failed (rv=%d)\n",rv); return
Changing the Top Via Header of the Message CHANGING THE TOP VIA HEADER OF THE MESSAGE The SIP Stack automatically handles the top Via header of its outgoing requests. After the destination address is resolved and the local address that will be used is known, the transmitter responsible for sending the request places this local address in the “sent-by” parameter of the top-most Via header. In some cases, the application does not want to reveal the address from where a request was sent.
ENUM Resolution Support RvSipRegClientSetTranscTimers() Sets the timers in a reg-client object. Setting timers in a reg-client effects all the transactions that this object handles. Note For all objects, you can also reset the timer back to the configuration values with the same API function, by supplying NULL to the set function instead of the RvSipTimers pointer. ENUM RESOLUTION SUPPORT According to RFC 3824, ENUM (E.
ENUM Resolution Support DNS list object. The single query result can be retrieved by using one of the Transport API functions for manipulating DNS list objects. For more information, see the Working with DNS chapter. ENUM EVENT The Transmitter API supplies an ENUM event in the form of a callback function, to which your application may listen and react. To listen to this event, your application should pass the event handler pointer to the TransmitterMgr object using RvSipTransmitterMgrSetEvHandlers().
ENUM Resolution Support Sample Code The following code sample illustrates an implementation of the ENUM callback using an abstract function that which performs regular expression parsing, called AppRegComp.
ENUM Resolution Support 392 HP-UX C SIP Stack Programmer’s Guide
20 CONFIGURATION INTRODUCTION This chapter describes the configuration of the SIP Stack. You will find information about the SIP Stack configuration parameters and how to set the parameters to suit your specific application requirements. INITIALIZATION SIP Stack configuration and memory allocation is performed upon initialization. You initialize the SIP Stack using the function, RvSipStackConstruct().
Configuration Parameters The following rules apply to parameters of the RvSipStackCfg structure: 1. If you set a parameter from group A to –1, the SIP Stack will use a default hard coded value. For example, maxCallLegs will be set to 10. 2. If you set a parameter from group B to –1, the SIP Stack will calculate the value of this parameter using the values of other parameters. 3. If you set a parameter from group A to an invalid value, rule 1 will apply. 4.
Configuration Parameters Remarks: Group B parameter: maxTransaction = maxCallLegs + maxSubscriptions If maxCallLeg = 0, then maxTransactions = 10 + maxSubscriptions maxRegClients The maximum number of register-clients the SIP Stack allocates. You should set this value to the maximum number of Register-Clients you expect the SIP Stack to handle simultaneously. Default Value: 2 Remarks: Group A parameter maxTransmitters The number of Transmitters that the SIP Stack allocates.
Configuration Parameters Element Pool MESSAGE POOL Used to hold and process all incoming and outgoing messages in the form of encoded messages or message objects. It is recommended that you configure the page size to the average message size your system is expected to manage. messagePoolNumofPages The message pool page number. Default Value: –1 Remarks: Group B parameter: messagePoolNumOfPages = max (2.5*maxTransactions, 4) messagePoolPageSize The message pool page size.
Configuration Parameters Group A parameter This parameter has a minimum value of 512. ELEMENT POOL Used by the SIP Stack to hold small pieces of information. For example, the call-leg holds its remote contact on an element pool page; a TLS session holds the hostname on such a page; and the transmitter uses this type of page in the DNS procedure. elementPoolNumofPages The number of pages in the element pool. Default value: –1 Remarks: Group B parameter: maxCallLegs*2 + 0.
Configuration Parameters Remarks: Group A parameter Note The SIP Stack can accumulate several SIP messages before starting to process them. These messages are placed in a queue and each message uses a different buffer. maxNumOfLocalAddresses The maximum number of local addresses that the SIP Stack may use simultaneously. Since the application can add and remove local addresses at runtime, the SIP Stack must know the maximum number of concurrently used addresses on initialization.
Configuration Parameters processingQueueSize The maximum length of the processing queue. The processing queue holds events such as network events. If the SIP Stack is running on a single thread, this thread will pop and process events from the queue. If the SIP Stack is running in multithreaded mode, the processing threads will process the events. Default value: –1 Remarks: Group B parameter. processingQueueSize = maxCallLegs + maxTransactions + maxRegClients + maxSubscriptions + maxConnections + 10.
Configuration Parameters Remarks: Group A parameter localUdpAddresses localUdpPorts Additional local UDP addresses to which the SIP Stack listens. The extra addresses will be used in multihomed host applications. Note: The addresses and ports array must be allocated according to the size given in numOfExtraUdpAddresses. Each of the entries of localUdpAddresses must be allocated as well, in order to contain the requested IP address.
Configuration Parameters Remarks: Group A parameter If you set the outbound Proxy port to –1, it will be discovered using the procedures defined in RFC 3263. CONNECTION ORIENTED CONFIGURATION tcpEnabled Indicates whether the TCP is enabled. If set to RV_FALSE, no connection will be allocated, and the SIP Stack will not support TCP. Default Value: RV_FALSE Remarks: Group A parameter maxConnections The number of connection sockets to be allocated by the SIP Stack.
Configuration Parameters Remarks: Group A parameter connectionCapacityPercent Determines the recommended percentage of opened connections that the SIP Stack is allowed to hold at any given moment from its pool of connections. RFC 3261 recommends that connections are kept open for some period of time after the last message was exchanged over the connection. However, the exact time period to leave the connection open is implementation-defined.
Configuration Parameters Each of the entries of localTcpAddresses must be allocated as well, in order to contain the requested IP address. localTcpAddress The local TCP address (IP) to which the SIP Stack listens. Default Value: 0.0.0.0 (Indicates the local IP address.) Remarks: Group A parameter localTcpPort The local TCP port on which the SIP Stack listens.
Configuration Parameters maxTlsSessions The maximum number of TLS sessions. A TLS session is the TLS equivalent on a TCP connection and contains TLS data required to manage the TLS connection. The SIP Stack will be able to handle a maximum of maxTlsSessions concurrent TLS connections. Default value: –1 Remarks: Group B parameter: maxTlsSessions = maxConnections (each opened connection can be used for TLS) TIMER CONFIGURATION retransmissionT1 T1 determines several timers as defined in RFC3261.
Configuration Parameters generalLingerTimer After a server sends a final response, the server cannot be sure that the client has received the response message. The server should be able to retransmit the response upon receiving retransmissions of the request for generalLingerTimer milliseconds.
Configuration Parameters cancelInviteNoResponseTimer When sending a CANCEL request on an Invite request, the User Agent waits cancelInviteNoResponseTimer milliseconds before timeout termination if there is no response for the cancelled transaction.
Configuration Parameters proxy2xxSentTimer A successful server INVITE transaction of a Proxy server includes only the INVITE request and the 2xx response. (The ACK is not part of the transaction). After sending the 2xx response the Proxy will wait proxy2xxSentTimer before the transaction will terminate. Default value: 0 Remarks: Group A parameter EVENT NOTIFICATION CONFIGURATION The following configuration parameters are used by the Event Notification (SUBSCRIBE/NOTIFY) feature.
Configuration Parameters Default value: RV_FALSE—the refreshing request will not be sent automatically. Remarks: Group A parameter bEnableSubsForking Indicates how to handle an incoming NOTIFY message that does not match an existing dialog and might be the outcome of a SUBSCRIBE message that was forked. If you set this parameter to RV_FALSE, a NOTIFY message that does not match any existing dialog will be handled as a general transaction.
Configuration Parameters processingTaskStackSize This parameter is relevant only for RTOS when the SIP Stack is executed in multithreaded mode. It defines the Stack size used by the processing tasks. The size is given in bytes. Default value: 30000 Remarks: Group A parameter ADVANCED FEATURES A number of the SIP Stack advanced features require the following special configuration parameters. ADVANCED BEHAVIOR CONTROL bOldInviteHandling Until version 4.
Configuration Parameters When a call-leg receives a 2xx response to an INVITE message after cancelling it, the application can manually send an ACK message, and the SIP Stack will not send a BYE message automatically. Default value: RV_FALSE Remarks: Group A parameter enableInviteProceedingTimeoutState Specifies whether to enable the INVITE_PROCEEDING_TIMEOUT state.
Configuration Parameters bDisableMerging Indicates how to handle an incoming request that has arrived more than once, following different paths—most likely due to forking. According to RFC 3261, if the request has no tag in the To header field, and the From tag, Call-ID, and CSeq exactly match those associated with an existing transaction—but the request does not match that transaction—it should be rejected with 482 (Loop Detected) response.
Configuration Parameters bResolveTelUrls Indicates that tel: schemes should be resolved by the SIP Stack. Version 4.0 implements the ENUM/TEL URL scheme. If this parameter is set to RV_TRUE, the SIP Stack will try to resolve tel URLs according to RFC 3764. If this parameter is set to RV_FALSE, the SIP Stack will call the RvSipXXXOtherURLAddressFoundEv() callback if the remote address contains a tel URL scheme.
Configuration Parameters Default Value: RV_TRUE Remarks: Group A parameter DNS maxElementsInSingleDnsList The maximum number of elements in single DNS List, regardless of the DNS list type. In total, when there are 3 DNS list types (SRV, Host Name, and IP address) a single DNS object may contain up to 3*maxElementsInSingleDnsList elements. Default value: 5 Remarks: Group A parameter maxDnsBuffLen The length of buffer used by the SIP Stack to read DNS query results arriving on TCP.
Configuration Parameters pDnsDomains A list of domains for the DNS search. The SIP Stack provides Domain Suffix Search Order capability. The Domain Suffix Search Order specifies the DNS domain suffixes to be appended to the host names during name resolution. When attempting to resolve a fully qualified domain name (FQDN) from a host that includes a name only, the system will first append the local domain name to the host name and will query the DNS servers.
Configuration Parameters SESSION TIMER sessionExpires The time at which an element will consider the call to be timed-out, if no successful INVITE transaction occurs beforehand. Default value: 1800 seconds Remarks: Group A parameter If minSE is larger than sessionExpires, sessionExpires must be updated to have the same value as minSE. minSE The minimum value for the session interval that the application is willing to accept.
Configuration Parameters Remarks: Group A parameter logContext The application context to the log. This context will be given to the application each time the pfnPrintLogEntryEvHandler() callback is called. Default Value: NULL Remarks: Group A parameter defaultLogFilters You can define a default logging level for all the SIP Stack modules using the defaultLogFilters parameter. The logging level will apply also to all Core and ADS modules.
Configuration Parameters Default Value: 0—no logging information Remarks: Group A parameter transactionLogFilters Transaction module log filters. Default Value: 0—no logging information Remarks: Group A parameter callLogFilters Call module log filters. Default Value: 0—no logging information Remarks: Group A parameter parserLogFilters Parser module log filters. Default Value: 0—no logging information Remarks: Group A parameter stackLogFilters SIP Stack Manager module log filters.
Configuration Parameters regClientLogFilters Register Client module log filters. Default Value: 0—no logging information Remarks: Group A parameter subscriptionLogFilters Subscription module log filters. Default Value: 0—no logging information Remarks: Group A parameter transmitterLogFilters Transmitter module log filters. Default value: 0—no logging information Remarks: Group A parameter adsFiltersCfg A structure that includes the log filter configuration for each of the ADS components.
C SIP Stack Libraries C SIP STACK LIBRARIES The C SIP stack libraries are available on both the IA and PA-RISC platforms. For both the IA and PA platforms, the libraries are available in 32-bit and 64-bit. The libraries are available with OpenSSL (TLS) support and also without OpenSSL (non-TLS) support. Depending on the type of support required, an application must be linked to the particular library.
Sample Applications Table 20-2 lists the C SIP stack libraries with TLS support. Table 20-2 LIBRARIES ON THE PARISC PLATFORM IA Libraries With TLS Support Type of Library Location 32-bit /usr/lib/hpux32/sip/TLS/ 64-bit /usr/lib/hpux64/sip/TLS/ The libraries on the PA-RISC platform are available with TLS support and without TLS support for both 32-bit and 64-bit applications. Table 20-3 lists the C SIP stack libraries without TLS support.
Sample Applications #define RV_TLS_TYPE RV_TLS_NONE 2. Set the architecture type RV_ARCH_BITS in the /usr/ include/sip/rvbuildconfig.h file to RV_ARCH_BITS_64, as follows: #define RV_ARCH_BITS RV_ARCH_BITS_64 3. Run the following command to compile the sample application: # cc +DD64 -I/usr/include/sip -I/usr/include/ sip/sip -I/usr/include/sip/ads -I/usr/include/ sip/common -c simpleSession.c where: +DD64 Instructs the compiler to generate the code for a 64-bit platform.
Sample Applications The simpleSession executable is generated in the current directory. 5. Run the "file" command on the simpleSession executable: # file simpleSession The following output displays: simpleSession: ELF-64 executable object file IA64 This denotes that the executable generated is a 64-bit for a IA64 platform. 6. Run the sample application as follows: # ./simpleSession EXAMPLE 2 Follow this procedure to compile and link 32-bit a sample application simpleTlsSession.
Sample Applications -I/usr/include/sip -I/usr/include/sip/sip -I/usr/include/sip/ads -I/usr/include/sip/common Sets the search path for header files. 4. Run the following command to link the sample application: # cc +DD32 -o simpleTlsSession ./ simpleTlsSession.o -L/usr/lib/hpux32/sip/TLS lrvsip -lrvads -lrvcommon -L/usr/lib/hpux32 -lnsl -ldl -lrt lpthread -lssl -lcrypto where: -L/usr/lib/hpux32/sip/TLS Sets the search path for the SIP libraries.
Sample Applications This shows that executable generated is a 64-bit for IA-64 platform. 6. Run the sample application, as follows: # ./ simpleTlsSession EXAMPLE 3 Follow this procedure to compile and link a 64-bit sample application simpleSession.c without TLS support on a 64-bit PA platform: 1. Set RV_TLS_TYPE in /usr/include/sip/common/ rvusrconfig.h to RV_TLS_NONE, as follows: #define RV_TLS_TYPE RV_TLS_OPENSSL 2. Set the architecture type RV_ARCH_BITS in /usr/include/ sip/rvbuildconfig.
Sample Applications simpleSession: ELF-64 executable object file PA-RISC 2.0 (LP64) 6. Run the sample application, as follows: # ./ simpleSession EXAMPLE 4 Follow this procedure to compile and link a 32-bit sample application simpleSessionTLS.c with TLS support on a 64-bit PA Platform: 1. Set RV_TLS_TYPE in /usr/include/sip/common/ rvusrconfig.h to RV_TLS_NONE, as follows: #define RV_TLS_TYPE RV_TLS_OPENSSL 2. Set the architecture RV_ARCH_BITS in /usr/include/sip/ rvbuildconfig.
Sample Applications -lcrypto , -lssl includes the openssl libraries needed for the TLS functionality -lrvsip -lrvads -lrvcommon specifies the SIP Stack libraries to be linked. 5. Run the "file" command on the executable: # file simpleTlsSession simpleTlsSession: PA-RISC2.0 shared executable dynamically linked -not stripped 6. Run the sample application as follows: # .
21 WORKING WITH THE MID-LAYER INTRODUCTION The SIP Stack provides a set of functions and function callbacks that enable the application to interface with some of the low-level elements of the SIP Stack, such as file descriptors and timers. The Mid-layer API can be divided into three main groups: Mid-layer Management API—includes a set of functions required for construction and destruction of the Mid-layer and other management functionality.
Mid-layer Management API MID-LAYER MANAGER HANDLE The Mid-layerMgr is identified by using the RvSipMidMgrHandle handle. INITIALIZING, CONSTRUCTING AND DESTRUCTING OF THE MID-LAYER The Mid-layer should be initialized before using any of the Mid-layer functions. Initialization of the Mid-layer sets the environment for Mid-layer operations. After initializing the Mid-layer, you should construct the Mid-layerMgr.
Mid-layer Management API registering on file descriptors. After this function is called, other threads will not be able to set timers or register on file descriptors. Using this function is not mandatory, but it is useful when you want to synchronize several application threads. RvSipMidDestruct() Frees all Mid-layerMgr resources. After calling this function, the application is not allowed to register on file descriptors or set timers. RvSipMidSetLog() Sets a log handle to the Mid-layer.
Mid-layer Timer API HandleError(); } ... /* Making sure that other threads will not be able to register. Calling this function is optional*/ RvSipMidPrepareDestruct(g_hMidMgr); /* You can wait here until all threads are synchronized */ /* Destructing the Mid-layer */ RvSipMidDestruct(g_hMidMgr); /* Terminating the Mid-layer environment */ RvSipMidEnd(); } MID-LAYER TIMER API The Mid-layer provides an API that enables the application to set and release timers.
Mid-layer Timer API RvSipMidTimerSet() Creates and sets a new application timer. This function returns a handle to the new timer object. When calling this function the application can supply a callback function pointer that will be called when the timer expires. The application can also supply a context that will be given back as one of the callback function parameters. To reset the timer, call RvSipMidTimerReset(). If the timer has expired, there is no need to call RvSipMidTimerReset().
Mid-layer Select API { RvSipMidTimerHandle hMyTimer = NULL; if(RV_OK != RvSipMidTimerSet(hMidMgr, 1000, TellTime, NULL, &hMyTimer)) { HandleError(); } } MID-LAYER SELECT API Some applications use file descriptors other than the one allocated by the SIP Stack (for other uses). An application may want to register these file descriptors on the same select() loop that the SIP Stack uses.
Mid-layer Select API RvSipMidSelectEv() When you register on a select()/poll() event, you provide the RvSipMidSelectEv() callback. When the select()/poll() exits with the file descriptor on which you registered, this callback will be called. This callback will provide you with the file descriptor, the event(s) that occurred, and a context. SAMPLE CODE The following sample code demonstrates how to register on a read event.
Mid-layer Select API Get the bit masks that the SIP Stack will use in the select() function. Run the select() function in your own code. Give the results back to the SIP Stack. Working in this mode is not recommended as long as the regular Select API that is described in Mid-layer Select API fits the application needs. If, however, the application must implement an application-level select() loop, it should work in a loop of five stages: 1. Get the select() bit mask from the SIP Stack. 2.
22 SAMPLE APPLICATIONS RUNNING THE SAMPLE APPLICATIONS The SIP Stack includes a rich set of small sample applications that demonstrate the usage of almost every feature of the SIP Stack in a clear and simple way. In addition, a full comprehensive GUI test application is provided. The SIP Stack includes the following sample applications: simpleSession—a very basic and fully documented console application that connects, accepts and disconnects a call.
Running the Sample Applications simpleInfo—extends the simpleSession example and demonstrates how to send a general request inside a call. In the example, an INFO request is sent. The source code of the simpleInfo is in the /usr/examples/sip/simpleInfo directory. simpleTransfer—demonstrates how to transfer a connected call using the REFER request, and the Call-leg and Subscription APIs. The source code of the simpleTransfer is in the /usr/ examples/sip/simpleTransfer directory.
Running the Sample Applications and an issued certificate. The source code of the simpleTlsSession is in the /usr/examples/sip/simpleTlsSession directory. advancedTlsSession—demonstrates how to implement the more advanced TLS callbacks that are used to override certificate validation decision and post connection assertion. The source code of the advancedTlsSession is in the /usr/ examples/sip/advancedTlsSession directory.
Running the Sample Applications connection in a new outgoing request. The source code of the simpleConnectionReuse is in the /usr/examples/sip/ simpleConnectionReuse directory. simpleTelSession—demonstrates the usage of tel URI and ENUM for connecting a SIP call. The source code of the simpleTel session is in the /usr/examples/sip/simpleTelSession directory.
INDEX A advanced behavior control 409 advanced features changing top via header of message 388 configuration parameters 409 ENUM resolution support 389 compilation 390 configuration 390 event 390 query 389 result 389 extension support 363 general URI scheme support 384 high availability 370 call-leg layer 370 subscription layer 370 multihomed host 366 API functions 366 DLA API 368 Dynamic Local Addresses (DLA) 368 other URI extension support 384 replaces header 372 receiving Invite message with replaces he
authentication object control 192 client authentication implementation 187 client authenticator callback functions 187 implementing MD5 callback function 189 implementing shared secret callback function 190 message in advance 193 multiple proxies 196 setting application callbacks 191 stand-alone transaction 196 authentication (server) applying server authentication mechanism 197 authenticator functions for server usage 208 call-leg server authentication functions 201 functions, callbacks 201 implementation
client general transaction 102 client invite transaction 106 client invite transaction state machine 109 compact form 163 configuration 27, 36 initialization 393 structure 393 configuration parameters 394 advanced features 409 advanced behavior control 409 DNS 413 extension support 412 session timer 415 symmetric response (rport) 415 event notification 407 log 415 memory pool allocation 395 multithreading 408 network 397 connection oriented 401 general configuration 397 outbound proxy 400 TCP configuration
notifier out-of-band subscription state machine 260 notifier state machine 251 notify status 254 out-of-band subscription 259 sending notification 257 subscriber out-of-band subscription state machine 261 subscriber state machine 249 subscription API 234 control 237 parameters 234 subscription entities 232 notification 232 subscription 232 subscription manager 232 subscription forking 264 API functions 266 call flow 267 configuration 269 events 266 multiple notify requests 264 subscription forking state mac
API functions 357 constructing, destructing 358 copying buffer to page 360 copying page into buffer 360 definitions 357 memory requirements 27 message API 22 message layer 18 message send failure 116 methods 23 mid-layer 427 threading considerations 427 mid-layer management API 427 constructing, destructing 428 manager handle 428 mid-layer select API 432 events 432 functions 432 select() loop 433 mid-layer timer API 430 control functions 430 events 431 handle 430 threading considerations 430 utility functio
parameters 131 registering application callbacks 141 working with handles 130 register-client manager API 140 register-client state machine 135 registrar 2 replaces header 25, 372 Resolver API 345 callbacks 346 control 345 parameters 345 resolver manager functions 346 resolvers 343 handles 345 resolver manager object 345 resolver object 343 responses 23 S sample applications running 435 security 23 server connections 302 general transaction 104 invite transaction 109 server cancel transaction 114 server ca
bad syntax start line 165 fixing bad syntax messages 168 handling bad syntax messages 165 types 2 SIP objects 19 body 175 body part 175 SIP session timer 25, 376 SIP Stack 15 objects 19 dialog (call-leg) 19 notification 20 register-client 19 subscription 20 transaction 20 SIP Stack architecture 17 message layer 18 stack manager layer 17 transaction layer 18 transport layer 18 user agent layer 17 SIP Stack object allocation parameters 394 SIP Toolkit standards conformance 22 SIP-T 24 SRV 330 stack manager AP
TLS configuration parameters 323 TLS connection 317 TLS connection API 317 TLS connection establishment 312 TLS connection events 318 TLS connection state machine 322 TLS connection states 320 TLS engine 314 TLS engine API 314 TLS Stack objects 313 TOS 385 transaction 20, 91 advanced states 116 message send failure 116 client cancel transaction 113 client cancel transaction state machine 114 client general transaction 102 client general transaction state machine 104 client invite transaction 106 client invi
undefined persistency 288 persistent connection handling 285 application connections 287 connection hash 286 connection owner 286 connection termination rule 286 raw buffer monitoring raw buffer events 327 raw buffer, message monitoring 327 server connection reuse 307, 310, 311 server connections 302 API 303 closing 305 events 303 server connection state machine 305 states 304 TCP transport 312 TLS transport 312 TLS Stack objects 313 transport layer API connection objects 293 handles 293 transport manager 2
448 HP-UX C SIP Stack Programmer’s Guide