Beruflich Dokumente
Kultur Dokumente
5.
Introduction to the Library 5.1. Features 5.2. RFCs Implemented 5.3. Terminology 5.4. Permissions 5.5. Architecture 5.5.1. The Exception Model 5.5.2. Threading Model 5.5.3. Class Diagrams 5.5.3.1. Transaction Class Diagram 5.5.3.2. Transport Class Diagram 5.6. Application Programming Interface 5.7. SIP Transaction Objects 5.8. The SIP URI 5.9. Walkthrough: Initiate a Session 5.10. Walkthrough: Accept Or Decline A Session Invite
30-31 31-32 32-34 34-36 36-37 37-38 38-41 41-42 42 42-44 44-46 46-48 48 48-51 51-55 55-57 58 58-60 60-64 64-66
6.
Configuration 6.1. Common Client Settings 6.2. Low-Level Client Settings 6.3. Internal Settings
7.
Working with the SipCore 7.1. Initialisation 7.2. Sip Core Behaviours 7.3. Event Processing 7.4. Listening For Incoming Messages 7.5. Sending Messages
67 67-69 69-70 70-73 73-74 74-76 77-78 78-79 79-82 82-83 83-85 85-87 88 88-89 89-90 90-91 91-95 95-96 97-98 98-99
8.
Working with Messages and Headers 8.1. SipMessage 8.2. Message Types 8.3. Adding Headers To Messages 8.4. Headers 8.5. Compact Form
9.
Working with Transactions 9.1. Transaction Entities 9.2. Transaction Types 9.3. Methods 9.4. State Machines 9.5. Timers
10.
10.2. The Authentication Exchange 11. Working with the Transport Layer 11.1. Sip Connections 11.2. Connection Reuse 11.3. Introduction to TLS in SIP 11.4. Event Processing 11.5. IPv6 11.6. Transport Buffers 11.7. Example 12. Working with SIP DNS
99-101 102 102-104 104-106 106-107 108-109 109-110 110-112 112-113 114 114-117 117-118 118
This document is intended to give you an overview of the SIP and SDP protocols and describes how to use Konnetic's Unity SIP .NET library for developing SIP applications. The current version is February 2011. New editions will have a new print date. Minor changes can occur without changing the print date. The latest version of the document is always available at: www.konnetic.com (http://www.konnetic.com/)
The C# .NET language. Basic Networking concepts. Threading and exception handling concepts.
Section 8
This document provides technical information about Konnetic's Unity SIP .NET SDK. It is intended to be read by application developers who are interested in creating and deploying SIP-based applications. Typically for applications that require high functionality communication and collaboration. This document consists of a general overview of the Unify SIP .NET API, guidance on some of the concepts involved with programming SIP applications using the Unify SIP .NET API.
Unity SIP .NET SDK installed on the development computer. A license for the product obtainable from Konnetic's website (http://www.konnetic.com/).
A compatible .NET VSS (Virtual Execution System) and framework. Konnetic products support Mono and the Microsoft CLR. We are committed to ensuring our products run on the platforms our customers demand.
For Windows Platforms All our products are written against Microsoft's .NET 2.0 Framework and thus run against versions 2.0, 3.0, 3.5 and 4.0. We have found most of our customers support this version set. We are unable to provide binaries compiled against other, earlier, versions (i.e 1.0 and 1.1) of the Framework.
Furthermore, our products are designed to run against Mono 2.6 and 2.7. Again earlier versions are not supported.
Programatically
Configuration File
Add the "license" element to the "<konneticSettings><sip>" configuration element. <konneticSettings> <sip> <!--The default SIP URI for the client--> <license key="PUT LICENSE KEY FROM EMAIL HERE"/> </sip> </konneticSettings>
License File
Find or create a konnetic.signalling.lic file and replace the whole contents of the file with the key. You may need to copy the konnetic.signalling.lic file into the application directory for each solution you use the evaluation in.
2.4 Ordering
At Konnetic, we want to ensure you can get the most from our products. We offer freely available fully functional evaluations of our software. You can deploy full purchased products royalty free. Each license grants one developer the ability to use and integrate the class libraries into the products they are developing. We include license management software in all versions of the software, thus there is a license key to associate with the class library in order to use the product. You can achieve this though application configuration, programmatically at runtime or using a license file. We have worked hard to balance a solution that is not onerous to you, but at the same time deters piracy of our IP.
partner site, Avangate.com. For further information, go to the purchase pages on the Konnetic web site: Konnetic Website (http://www.konnetic.com/purchase/purchase.aspx)
This End User License Agreement ("EULA") is a legal agreement between you (either an individual or an entity) and Konnetic for the software product identified above, which may include user documentation provided in online or electronic form. By installing, copying, or otherwise using the SOFTWARE, you agree to be bound by the terms of this EULA. If you do not agree to the terms of this EULA, do not install or use the SOFTWARE. 1. GRANT OF LICENSE Konnetic grants to you as an individual or entity a non-exclusive License to make and use copies of the SOFTWARE in the manner provided below. The software is licensed, not sold. (a) Evaluation License Konnetic grants to you as an individual, a personal, nonexclusive License to install the SOFTWARE for the sole purposes of evaluating the SOFTWARE. You may evaluate the SOFTWARE for a period of thirty (30) days. After this period, you shall either (i) delete the SOFTWARE and all related documentation from all computers onto which it was installed or copied, or (ii) purchase a Single Developer License from Konnetic or one of its authorized suppliers to purchase the SOFTWARE. You may not under the terms of the evaluation License distribute any portion of the SOFTWARE or products generated using the SOFTWARE. (b) Single Developer License After you have purchased the License for the SOFTWARE, and have received a registration code enabling the registered copy, you are licensed to copy the SOFTWARE only into the memory of the number of computers corresponding to the number of Licenses purchased and activate the SOFTWARE using the supplied registration code. The primary user of the computer on which each registered copy of the SOFTWARE is installed may make a second copy for his or her exclusive use on a second computer. Under no other circumstances may the SOFTWARE be operated at the same time on more than the number of computers for which you have paid a separate License fee. You may not duplicate the SOFTWARE in whole or in part, except that you may make copies of the SOFTWARE for backup or archival purposes. You have a royalty-free right to distribute the portions of the SOFTWARE designated as "Redistributable Code" under the terms below. 2. REDISTRIBUTABLE CODE Portions of the software are designated as "Redistributable Code". The Software documentation
subject to the requirements described below. You have a royalty-free right to distribute the portions of the SOFTWARE designated as "Redistributable Code" only if: (a) You have purchased a License for the SOFTWARE. (b) You distribute only the portions of the SOFTWARE designated as "Redistributable Code". (c) You use and distribute the "Redistributable Code" only in conjunction with the binary files that make use of them as a part of your software product. (d) Your product(s) and application(s) must add significant and primary functionality to the SOFTWARE; (e) You do not expose, document or make public the SOFTWARE API (Application Programming Interface); (f) Your software product may not, in the reasonable opinion of Konnetic, compete with any Konnetic product. (g) You agree to indemnify, hold harmless, and defend Konnetic and its suppliers from and against any and all claims or lawsuits including attorney's fees that arise or result from the use or distribution of your software product. 3. RESTRICTIONS You must not redistribute the registration codes provided, neither on paper nor electronically outside of that required to activate the SOFTWARE. You must not redistribute any original or modified source code file or any portion of the source code contained within the files. You agree not to use the knowledge acquired from the source code in order to develop for yourself or any third party any program that is similar to or competitive with the Software. You are not allowed to port the source code to other programming languages. You may not reverse engineer copy, duplicate or distribute the License schema that is needed to use the SOFTWARE in a design, development or runtime environment. You may not disassemble, decompile or reverse engineer the SOFTWARE or any portions of it. You may not rent, lease, or lend the SOFTWARE. You may permanently transfer all of your rights under this EULA provided you transfer all copies of the SOFTWARE (including copies of all prior versions if the SOFTWARE is an upgrade) and registration codes and retain none, and the recipient agrees to the terms of this EULA. 4. TERMINATION Without prejudice to any other rights, Konnetic may terminate this EULA if you fail to comply with
10
SOFTWARE. You may terminate this License at any time by destroying the original and all copies of the SOFTWARE in whatever form. 5. COPYRIGHT The SOFTWARE is owned by Konnetic and is protected by Australian copyright laws and international treaty provisions. You may not copy the printed materials accompanying the SOFTWARE (if any), nor print copies of any user documentation provided in on-line or electronic form. 6. LIMITED WARRANTY THE PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL THE AUTHOR or AUTHORS BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF THE USE OF THE PROGRAM, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT YOU HAVE READ THIS LICENSE, UNDERSTAND IT AND AGREE TO BE BOUND BY ITS TERMS AS THE COMPLETE AND EXCLUSIVE STATEMENT OF THE AGREEMENT BETWEEN US, SUPERSEDING ANY PROPOSAL OR PRIOR AGREEMENT, ORAL OR WRITTEN, AND ANY OTHER COMMUNICATIONS BETWEEN US RELATING TO THE SUBJECT MATTER OF THIS LICENSE. 7. LIMITATION OF LIABILITY IN NO EVENT SHALL KONNETIC OR ITS SUPPLIERS BE LIABLE TO YOU FOR ANY CONSEQUENTIAL, SPECIAL, INCIDENTAL, OR INDIRECT DAMAGES OF ANY KIND ARISING OUT OF THE DELIVERY, PERFORMANCE, OR USE OF THE SOFTWARE, EVEN IF KONNETIC HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY EVENT, KONNETIC'S LIABILITY FOR ANY CLAIM, WHETHER IN CONTRACT, TORT, OR ANY OTHER THEORY OF LIABILITY, EXCEEDS THE LICENSE FEE PAID BY YOU.
11
Technical Overview
3.1 Introduction
Session Initiation Protocol (SIP) was designed from the bottom up to connect people and devices whenever and wherever they are in order to engage in a (possibly lengthy) exchange of information. Existing protocols, such as HTTP and SMTP, were not purpose-built for this essential human activity, and so SIP was born to fill the gap. However, SIP borrows from these two other protocols heavily. From using HTTPs message exchange pattern, message format and encoding, to SMTPs URI scheme. In 2002 revised version of the SIP standard was formalised into the Internet Engineering Task Forces (IEFT) standardisation process as RFC3261. Because of the open nature of the IETF standards process, the fact SIP is text based and shares many features with existing specifications, it has been readily understood, extended and implemented.
3.1.1 Clients
We naturally associate the concept of client software to the end users. This is even more applicable with SIP as it is indifferent to the device or application the person uses and attempts to abstract away the internet plumbing and make the person internet addressable. The User Agent (UA) is the entity typically hosted on client software and associated with end users. It has two modes of operation:
As a User Agent Client (UAC): Generates and sends requests those to servers (which may include a UAS, see next), and receives responses in return.
As a User Agent Server (UAS): Receives and processes requests, and generates responses.
12
SIP servers are instrumental in the location of clients and the efficient and correct routing of SIP messages.
Proxy Server: These elements are involved in routing the SIP Request to the correct UAS and SIP Responses to the correct UAC. They are the most common type of server in a SIP environment. If an exact address of the recipient is not know at elaboration the client sends the request to a proxy server which forwards it onto another proxy server closer to the end point or the ultimate recipient itself.
Redirect Server: A redirect server accepts requests from a client and responds to the client with a new address or different route path to the recipient. They are important in supporting mobility when a recipient has moved location.
Registrar: These servers act as current repository of a clients location often utilising a separate Location Server. User Agents register with a Registrar on start up or when the client changes the point of attachment to the network.
B2BUA: These logical entities act in a dual capacity in that they receive requests like a UAS, process the request further in some manner, then behave as a UAC and forward the processed request on. B2BUAs maintain state between calls and participate in SIP transactions providing tight control over the exchange. A stateful Proxy Server may contain a B2BUA.
Request: sent from client to a server and define the operation sought by the client. Response: sent from server to a client and provide the status of that request
3.2.1 Requests
A SIP request is characterised as a method much like HTTP, and is considered a verb, since it requests actions to be performed by other User Agents or servers. RFC3261 defines six methods with subsequent standards defining the remaining extension methods (from INFO onwards).
Method Description
13
SUBSCRIBE Used to request receipt of future NOTIFY or PUBLISH requests. UPDATE Modifies session parameters in mid-call.
3.2.2 Responses
SIP Response messages are always sent in reply to a request. They convey status updates, confirmations, directions and error codes back to the UAC originating the request. Responses are characterised as either provisional or final and every response must be identified by a 3-digit code. Response Types Six classes of response have been defined and are categorised using the 3-digit code. The first five are borrowed from HTTP; the sixth is new to SIP.
14
1xx Provisional
5xx Server Failure The server is unable to fulfil the request because of an internal error. 6xx Global Failure
Within each class, numerous response codes have been predetermined - some copied from HTTP.
# 100 180 182 200 301 302 400 401 403 404 408 Reason Phrase Trying Ringing Queued OK Moved Permanently Moved Temporarily Bad Request Unauthorised Forbidden Not Found Request Timeout Description The next hop received the request. Attempting to alert the user. Temporarily unavailable and request is in a queue (not rejected). The request has succeeded. User is no longer available at the address given in the Request URI. Retry the request at a new address given in the Contact header. Could not understand or process correctly the request. The request either failed authentication or needs more information. The server is refusing to process the request. Do not retry. The server cannot identify the user in its domain. The server could not process the request in a reasonable time.
15
Temporarily Unavailable The called party is currently unavailable. Ambiguous Busy Here Server Internal Error Message Too Large Declined The Request URI is ambiguous. The called party is currently not willing or able to take the call. The server encountered an unexpected condition. The message length exceeded a determined limit. The user explicitly refused to accept the request.
Warning Header Field The Warning header field is used to carry additional information about the status of the response. The header defines a 3-digit code between 300 and 399, the host name and a warning text.
Start-Line: formatted as a Request-Line for Requests or a Status-Line for Reponses. Headers: Named attributes that provide additional information about the message. Separator Line: Separator between header and body. Body: binary or textural payload. Typically Session Description Protocol (SDP) or a message text.
The start line, each header line and the separator line is terminated by a [CRLF] sequence.
16
Request-Line: Contains a method, URI and ends with the protocol version ("SIP/2.0"). Status-Line: Starts with the protocol version, followed by a numeric status code and is completed with a short textural reason.
3.3.2 Headers
Headers follow the same generic header format as HTTP. Each consisting of a case-insensitive ASCII encoded name and colon followed by a value which is sometimes UTF8 encoded and usually casesensitive. Each header can have one or more semi-colon separated parameters appended to the value, providing additional tags and features. header-name: header-value(;parameter-name=parameter-value)*[CRLF] Each header can be separated on to different lines using a [CRLF][TAB or SPACE] sequence (known as folding). Whats more, multiple headers with the name same e.g. Contact can appear on separate lines, or, can be placed on the same line separated by commas. For example: Contact: <sip:alice@atlanta.com> Contact: <sip:alice1@chicago.com> Can be represented as: Contact: <sip:alice@atlanta.com>, <sip:alice1@chicago.com> Or using folding: Contact: <sip:alice@atlanta.com>, <sip:alice1@chicago.com>
3.3.3 Body
A message body describes the session (using SDP) or contains opaque text or binary body parts containing the payload related to the session (e.g. MIME or Message formats). Bodies can appear in request or response messages.
17
2. Create the Via header, the Via header indicates to the recipient the return path. invite.ViaHeaders.Add(new ViaHeaderField(new IPDomainPort("122.181.8.8:11506"), TransportProtocol.Udp)); 3. Create the addresses of the sender and recipient. The SipUris can be an IP address, but Fully Qualified Domain Names are recommended. Display names are possible. For security reasons the From header is allowed to by anonymous if desired. invite.From.Uri = new SipUri("sip:bob@897s.aarhus.com"); invite.From.DisplayName = "Bob"; invite.From.Tag = "769122"; invite.To.Uri = new SipUri("sip:alice@ml99.odense.com"); invite.To.DisplayName = "Alice";
4. Create the unique identifiers for the call and the conversation. The CallId is a unique value for the session. The sequence is incremented in subsequent Requests. The To, From, and Call-ID tuple provides a unique key for a call. invite.CallId.CallId = "afh7989asdfhf@ml99.odense.com"; invite.CSeq.SequenceNumber = 3434534; invite.CSeq.Method = SipMethod.Invite;
5. Create the alternate contact information for the sender. invite.ContactHeaders.Add(new ContactHeaderField( new SipUri("sip:alice2@vejle.com")));
18
2. Add the alternate contact information. This time it is for Bob. okMessage.ContactHeaders.Add(new ContactHeaderField(
19
3. Finally add the content definitions. okMessage.ContentType.MediaType = "application"; okMessage.ContentType.MediaSubType = "sdp"; okMessage.ContentLength = 132;
20
Session Setup
Alices UA sends an INVITE message to Bobs SIP address (i.e. <sip:bob@897s.sydney.com>). The message contents are a Session Description Protocol message describing the expected media exchange.
Bobs UA receives the INVITE and responds with a 100 Trying message. The UA then attempts to attract the attention of Bob, and simultaneously sends a 180 Ringing message to Alice.
Bob respond and is UA sends a 200 OK message. The 200 OK contains the SDP message Bob is agreeing to.
Finally, Alices UA acknowledges receipt of the OK with an ACK request. Media streams are established directly between Alice and Bob.
Bob hangs up and his UA initiates a session termination by sending a BYE request to Alice. Alices UA response with a 200 OK.
21
22
Technical Overview
4.1 Introduction
With the advent of protocols used to negotiate and define a communication sessions parameters (e.g. Session Initiation Protocol), there was a need to explain the purpose and enrolment process. Session Description Protocol (SDP), defined in RFC4566, achieves that by providing a format for session characterisation and media definition. As part of a session negotiation, the parties are expected to agree on the descriptive values, timings, their respective capabilities and desired media formats. This exchange is referred to as the Offer/Answer Model and is formalised in RFC3264. SDP can be used with a number of transport protocols, such as Session Announcement Protocol (SAP), Session Initiation Protocol (SIP), Hypertext Transfer Protocol (HTTP), and others.
Session name. Time(s) the session is active. The media comprising the session. The owner/originator of the session. How to receive the media (addresses, ports etc.).
Bandwidth to be used by the conference. The purpose of the session. Contact information for the person responsible for the session. Time zone information. Session attributes extending SDP.
The encoding of the protocol is primarily UTF8 (descriptive fields can have other encoding as
23
specified with a 'charset' attribute defined later). Each piece of information is conveyed in a field. Each field is separated from the next by a carriage return/ line feed sequence [CRLF]. The form of each field is: <type> = <value> Where the <type> is a case-insensitive and unique single character field name. And <value> is structured text whose format depends upon <type>. They are separated by an unpadded '=' (equal) sign.
v o s
24
Note: M - mandatory; O- optional; C- Conditional (Connection Data must appear in either the Session or Media descriptions).
Field
Type
Timing
Repeat Times r
Times are represented as Network Protocol Time (RFC1305): the number of seconds since 1900; intervals can be represented with NTP times or in typed time: a value and time units (days ('d'), hours ('h'), minutes ('m') and seconds ('s')) sequence. Thus an hour meeting from 10am on 1st August 2010, with a single repeat time a week later at the same time can be represented as: t=3487140000 3487143600 r=604800 3600 0 Or using typed time: t=3487140000 3487143600
25
Media Descriptions Session Information Connection Data Bandwidth Encryption Keys Attributes
Same as above
A property form: "a=<flag>" conveys a property of the session. A value form: "a=<attribute>:<value>" provides a named parameter.
26
Maps an RTP payload to the encoding, format and clock rate. Tools should start in receive-only mode. Tools can start in send and receive mode. Types include "broadcast", "meeting" and "moderated" The character set used in the session name and information fields. The default language for the session.
Type
type:<conference type>
Charset
charset:<character set>
Language
lang:<language tag>
27
the originator. The session ID is 2890844526 and the version is 89. The session was created on machine 214.191.7.5. sdp.Origin.UserName = "jdoe"; sdp.Origin.SessionId = 2890844526; sdp.Origin.SessionVersion = 89; sdp.Origin.Address = new IPDomain("214.191.7.5"); 3. Add the session name and information including a pointer to a website with more info. sdp.SessionName = "SDP Implementation"; sdp.SessionInformation = "A Seminar on the session description protocol"; sdp.Uri = new Uri("http://www.mel99.melbournesdp.com/documents/sdpseminar.html"); 4. Add the contact information for the person responsible. The email for John Doe, which includes a full name. sdp.Emails.Add(new EmailHeaderField("jdoe@mel99.melbourne.com", "John Doe")); 5. Add the connection information about how to receive the session. The address can be either an IP address or a Fully Qualified Domain Name. In this example an IP connection to the session host is used. sdp.Connection.Address = new IPHost("124.198.100.6"); 6. Add the timings. There are at least one and can be more than one time field. A good API will allow you to provide either NTP time or a DateTime. The output for times will always be the number of seconds since 1900 for the timings (3487140000 and 3487143600 respectively). These timings represent an hour meeting at 10am on the 1st August 2010. TimeDescriptionHeaderField td = new TimeDescriptionHeaderField(); td.Timings.Start = new SdpTime(new DateTime(2010, 7, 1, 10, 0, 0, 0)); td.Timings.Stop = new SdpTime(new DateTime(2010, 7, 1, 11, 0, 0, 0)); sdp.TimeDescriptions.Add(td); 7. Now, we can add the attributes for the session. This attribute is scoped to the session and indicates that applications should begin the session in receive-only mode.
28
49170 using RTP Profile for Audio and Video Conferences with minimal Control running over UDP. The final zero is extra parameter information for RTP/AVP. MediaHeaderField mh = new MediaHeaderField(SdpMedia.Audio,49172, SdpMediaProtocol.RtpAvp,"0"); sdp.MediaDescriptions.Add(new MediaDescriptionHeaderField(mh)); 9. The second media description is for video on port 51372 using RTP Profile for Audio and Video Conferences with minimal Control running over UDP. The final 31 is extra parameter information for RTP/AVP. This attribute is scoped to the media description. Any presentations will be in portrait. MediaHeaderField mh1 = new MediaHeaderField(SdpMedia.Video, 51372, SdpMediaProtocol.RtpAvp, "31"); MediaDescriptionHeaderField md = new MediaDescriptionHeaderField(mh1); md.Attributes.Add(new AttributeHeaderField("orient", "portrait")); sdp.MediaDescriptions.Add(md);
Note: The two media descriptions (the lines beginning with m), define an audio and a video profile. These profiles are described in the Real Time Protocol (RTP) specification, RFC3550, and its travel companion RTP Profile for Audio and Video Conferences with Minimal Control, RFC3551.
The resulting SDP message should look exactly like the following: v=0 o=jdoe 2890844526 89 IN IP4 214.191.7.5 s=SDP Implementation i=A Seminar on the session description protocol u=http://www.melbournesdp.com/documents/sdpseminar.html e=jdoe@mel99.melbourne.com (John Doe) c=IN IP4 124.198.100.6 t=3487140000 3487143600
29
30
Konnetic's Unity SIP .NET SDK is a class library written in C# that runs on Microsoft's CLR or Mono. The libraries provide an object model for developing SIP (IETF RFC 3261) based applications and services written against the .NET Framework 2.0 and later. Many of SIP's requirements and demands have been abstracted away leaving the developer to concentrate on high-level high-value application implementation. But at the same time the library still allows low-level configuration and control over SIP message flows using an event-based model. The library provides advanced multi-threaded connection management designed to efficiently take advantage of multi-processor or multi-core hardware environments achieving high-performance in modern processors. It also enables a reliable communication model by supporting TCP (Transmission Control Protocol); or provides for authentication and encryption through the use of TLS (Transport Layer Security); or allows higher throughput by using UDP (User Datagram Protocol). SIP methods currently supported include REGISTER, INVITE, OPTIONS, ACK, BYE, CANCEL, INFO, UPDATE and MESSAGE. SIP URIs are an important and complex part of the SIP standard. The Unity SIP .NET SDK provides a type safe SIP URI mechanism derived from the .NET Framework's System.Uri, System.UriParser and System.UriBuilder classes. Other important features include full support for HTTP Digest Authentication, SIP DNS and an SDP library.
5.1 Overview
This section describes the SIP library architecture, the relationship between the objects, API, standards and different kinds of features. Konnetic's implementation of SIP is designed primarily for clients, but can be used in server applications also. It allows you to build the following types of applications and services:
Media over IP. Collaboration tools. A building block to develop a wide range of applications from mobile apps to desktop clients applications and services.
31
Develop complete solutions for .NET managed platforms that implement call-level, transactionlevel and message-level functionality.
5.1 Features
The SIP Stack component of the SIP Stack was developed in conformity with the specifications of RFC 3261 and various SIP extensions (see RFCs Implemented (Section 5.2)).
5.1.1 Methods
The SIP Stack supports baseline SIP methods, such as INVITE (Re-INVITE), ACK, BYE, CANCEL, OPTIONS and REGISTER. In addition extension methods supported are INFO, UPDATE and MESSAGE
5.1.2 Responses
The SIP Stack supports all response code classes (1xx to 6xx) specified in RFC 3261.
5.1.5 Interoperability
The Unity SIP Library passes RFC and European Telecommunications Standards Institute testing suites.
5.1.6 Parsing
Parsing of incoming messages is a fundamental feature of any SIP Library. Unity SIP Library uses a unique and powerful directed Deterministic Finite Automa engine to manage all header parsing.
5.1.7 Transports
32
5.1.8 Security
The SIP Stack can authenticate any SIP request using the Digest authentication scheme in conformity with the SIP specification. Both Client authentication and Server authentication (mutual) are supported. In addition Message Integrity (Auth-Int) is supported.
5.1.9 Multithreading
The SIP library runs in an internally multithreaded mode. Your application may either be singlethreaded or multithreaded. The SIP library uses synchronization mechanisms to ensure multithreading safety at the level of individual objects, such as dialogs and transactions, as well as groups of object as in the transport layer. The SIP library makes use of new threads to listen for incoming messages, and spawns new threads to handle each new message received. The main implication for developer's is exceptions occuring within the multithreaded environment are marshalled to either an event (e.g. OnListenerAborted event on the SipCore) or assigned to an exception property to be thrown on subsequent access to the object (e.g. Parsing exceptions on a SipMessage).
Default Message Properties Message Limits Network parameters Timer values Proxy Servers Miscellaneous
33
RFC3263
RFC3261
RFC2976 RFC2782
A DNS RR for Specifying the Location of None Services (DNS SRV) HTTP Authentication: Basic and Digest Access Authentication None
RFC2617
RFC2119
34
Testing of the library against industry standards in important to Konnetic. The following test suites have been used to verify that Unity SIP Library is fully compatible with the standard. Title RFC4475: SIP Torture Test Messages ETSI: Conformance Test Specification for SIP None Proxy, Registrar, Redirect functionality was not tested Missing Functionality
5.3 Terminology
Connection An association between two endpoints which carries packets across networks. Each endpoint is represented by a network address and port. In SIP, this concept is sometime referred to as a Flow. In the Unity SIP .NET API, a connection can use either TLS, TCP or UDP transport. Konnetic's Unity SIP .NET API supports two types of connections: inbound and outbound. An inbound connection listens for incoming packets on an assigned local endpoint. Outbound connections initiate transmissions from the local endpoint to the correspondent. Outbound connections will typically use an ephemeral port number and subsequently listen on that port for responses. Destination Tuple A destination tuple contains the information needed to connect to a remote network device. It is formed of the IP Adddress of the remote device, the remote listening port and the transport protocol. Clients can either use the libraries DNS facility to resolve addresses, ports and transports, or can send messages directly using a destination tuple contained in the DestinationTuple object. Dialog A dialog represents a peer-to-peer SIP relationship between two or more user clients that persists for some time. It is analogous to a conversation or call, and is sometimes refer to as such. A session is typically associated with a dialog. Header Field
35
A header field is a component of the SIP message header. A header field can appear as one or more header field rows. Header field rows consist of a header field name and zero or more header field values. Multiple header field values on a given header field row are seperated by commas. Some header fields can only hvae a sinlge field value, and as a result, always appear as a single header field row. Outbound Proxy A proxy that receives requests from a client, even though it may not be the server IP Address resolved by the Request-URI. Typically, a User Agent is manually configured with an outbound proxy, or can learn about one through auto-configuration protocols. The ProxyServers config section allows the client application to configure the default outbound proxy servers for request messages. Alternative mechanisms are available to provide the proxy services, including on the SipCore. The proxy servers are used by the outgoing message processsors to create a route-set on the message (unless a route header field is already present). The processor calculates the remote address of the message according to RFC3261 and RFC3263 and takes into account the existance of outbound proxy servers, Route header fields and loose routing rules. There is a separate configuration for secure proxy servers to be configured as an outbound route-set for all secure transmissions. Only proxy servers with secure SIP URIs are allowed (e.g. sips:proxy3.com) for secure transmissions. Route Set A route set is a collection of ordered SIP or SIP URI which represent a list of network nodes (typically proxies) that must be traversed when sending a particular request. A route set can be learned, through headers like Record-Route, or it can be configured. SDP Session Description Protocol, an IETF Internet standard (RFC 4566). It defines a format for representing multimedia sessions. SDP objects are carried in the body of SIP messages and, based on the offer/answer model, are used to negotiate the media characteristics of a session between users. Session A session provides the control channel in which a user client can invite another user client to
36
independent message exchanges (Message Exchange Patterns). A SIP transaction consists of a single request and all following responses to that request. Two categories of transaction exist: those that are initated with an INVITE request (Invite Transactions), and those that are not (Generic Transactions). User Client The device that hosts the SIP-based application.
5.4 Permissions
The Unity SIP Library relies upon certain external resources to operate. Those resources must be available at runtime and access-control permissions must be set so as to allow the executing thread to access them. Additionally the library issues Code Access Security (CAS) demands upon the call stack at certain points in the operation. The resources include:
Sockets - the SIP Library is a networked library and requires unrestricted access to network sockets. A CAS demand is placed on the call stack whenever the library access the network.
DNS - Domain Name Service querys are a fundamental part of using SIP. The library requires access to the DNS servers specified in the Konnetic.Net.NetworkInformation object. A CAS demand is placed on the call stack whenever the library issues a (non-cached) DNS query.
File IO - The library must have permission to read the configuration file, and any files it dynamically links to.
Reflection - Internally the Unity SIP Library uses information about certain types when executing. Furthermore, permission to invoke methods on types may be required in future
37
5.5 Architecture
The following diagram illustrates the overall architecture of the Unity SIP .NET API and important dependencies.
38
messages, acknowledgements and retransmissions using the transactional Timer. The transaction layer maps incoming messages to existing transactions and dialogs.
5.5.3 Transport
The transport layer handles SIP networking I/O. This layer manages UDP sockets and TCP connections, as specified in RFC3261, and sends and receives messages. Secure transmission is provided via TLS certificate exchange on a client-only or mutual basis.
5.5.4 Messages
Messages handle parsing and encoding of SIP messages. The message objects allow the strongly typed browsing and editing of the contents of SIP messages and also comparison of message parts, such as the SIP address. Validation of updates is provided as specified in RFC3261.
5.5.6 Authentication
SIP employs HTTP Digest authentication when establishing identiyy between elements. The Unity SIP Library uses a sophisticated authentication managment routine to control the lifetime of HTTP Digest exchanges.
5.5.7 DNS
RFC3263 governs how SIP resolves SIP URIs to IP Addresses. The Unity SIP Library provides a Linq friendly interface to the DNS querys and cache.
39
thrown when a method cannot complete its task as indicated by its name. All user defined exceptions derive from SipException, which in turn derives from System.Exception. The following exceptions are explicitly thrown within the Unity SIP .NET API, but other exceptions may originate from the Framework Class Library and are propagated up through the Unity SIP .NET API stack. For example, a System.Net.Sockets.SocketException may be thrown by the underlying network subsystem, or a resource constraint may cause a System.OutOfMemoryException to be thrown. Application designers need to consider subsystem exceptions when designing a robust exception policy.
ArgumentNullException
ArgumentOutOfRangeException
FormatException
InvalidOperationException
ObjectDisposedException
TimeoutException
40
SipAggregateException
The aggregate exception wraps one-or-more inner exceptions. The exception is used to marshal a number of exceptions beyond the thread boundary. For example, the parsing of incoming message occurs on a thread spawned within the Transport Layer. Any parsing exceptions are wrapped in a SipAggreagateException and assigned to the SipMessage. The exception may be thrown on subsequent access to the SipMessage. The exception that is thrown when a generic SIP error occur. All SIP exceptions ultimately derive from this exception. The exception that is thrown when a SIP formatting error occurs. The exception that is thrown when parameters of a SIP message exceed the limit set. The exception that is thrown when a value is semantically out of allowable range or a numeric overflow occurs. The exception that is thrown when the parse method is invoked and it is detected that the passed arguments would result in illegal SIP syntax or semantics. It does not signify an invalid object. The exception that is thrown when an exception occurs in the authorization of sip messages. The exception that is thrown concerning an error in the transactional state machine for the message. The exception that is thrown when an error occurs in the transport layer. The exception that is thrown when a method is invoked and it is detected
SipException
SipFormatException
SipMessageSizeLimitException
SipOutOfRangeException
SipParseException
SipSecurityException
SipTransactionException
SipTransportException
SipUriException
that the passed arguments would result in illegal SIP URI syntax or semantics. The exception that is thrown when a SIP formatting error occurs when dealing with the SipUri class.
SipUriFormatException
41
42
because they will not be caught and handled appropriately within the Library and failure will result in the termination of the application. The library does not raise events or invoke application-supplied callbacks inside syncronisation primatives.
43
44
45
46
Initialisation and termination. Configuration Event management Start Listening for incoming messages Send outgoing messages Authorization
47
The SipTransactionStateManager object enables you to terminate dialogs, modify exiting dialogs (re-INVITE) and more. The Dialog objects provide a set of events that provide you with the ability to add your own call processing logic to the application. Dialogs are created automatically by Invite Transactions. Transactions The SipTransaction derived types (GenericClientTransaction, InviteClientTransaction, GenericServerTransaction, InviteServerTransaction) enable you to manage transactional state. The transaction may be related to a dialog (e.g. for a trasnaction begun with an INVITE) or not (e.g. OPTIONS related transactions). Using the API you can create new transactions, send outgoing requests, and respond to incoming requests. However, SipTransactions are typically automatically created when sending a request. Transactions provide a set of events that enable you to control some of the behaviour. In addition to their usage in clients you can use the transactions to implement SIP servers such as Registrars and Proxies.
48
The SipConfiguration object enables low-level configuration of the client parameters, transaction timers, message limits and behaviour.
Call-ID. The SIP address of both endpoints (To and From headers). The tag value attached to the To header.
In the SIP library, a Dialog object stores states and manages transactions on behalf of the dialog.
5.7.2 Transactions
A SIP transaction involves all messages sent between a client and a server for the purposes of completing one signalling action, such as call establishment and call termination. The dialog to which a transaction may belong and an Command Sequence identifier called CSeq uniquely identifies the transaction. In the SIP library a transaction stores the state and manages the progress through the use of timers, event handling and state machines. A transaction can also be used outside of the context of a specific dialog to accomplish User Agent signalling action.
49
domain name, or a numeric IP address. Additionally, SIP and SIPS URIs may contain parameters and headers (although headers are not legal in all contexts). A SIP or SIPS URI identifies a communications resource. Like all URIs, SIP and SIPS URIs may be placed in web pages, email messages, or printed literature. They contain sufficient information to initiate and maintain a communication session with the resource. The following example shows the general syntax for a SIP URI. Refer to section 19 of the IETF RFC SIP Standard (http://www.ietf.org/rfc/rfc3261.txt). The "sip" and "sips" schemes use a form similar to the mailto URL, allowing the specification of SIP request-header fields and the SIP message-body. This makes it possible to specify the subject, media type, or urgency of sessions initiated by using a URI on a web page or in an email message. SIP URI sip:user:password@host:port;parameters?headers The format for a SIPS URI is the same, except that the scheme is "sips" instead of sip.
Alternatively the SipUriBuilder can be used to construct a SipUri. The default scheme is "sip" throughout the library.
50
Example
Default
Description
sip
sip
Identifies the scheme. The identifier of a particular resource at the host being addressed. A password associated with the user. The host providing the SIP resource.
user
alice
password
password
host
konnetic.com The default is 5060 for a "sip" scheme and 5061 for a "sips" scheme.
port
2100
parameters
transport=tcp;method=REGISTER
Parameters influence SIP transport and processing. URI parameters are added after the hostport component and are separated by semi-colons.
51
mechanism within a URI. They provide additional information and can be used to construct a SIP Request from the URI.
headers
to=alice%40atlanta.com
user
ip
method
INVITE
The method of the SIP request constructed from the URI may be specified with the method parameter. Indicates the server address to be contacted for this user, overriding any address derived from the host field. Determines the time-to-live value of the UDP (User Datagram Protocol) and must only be used if maddr is a multicast address and the transport protocol is UDP
maddr
ttl
transport
For "sip" it is Determines the transport protocol to be used for sending SIP messages. For UDP. For "sips" a SIPS URI, the transport parameter must indicate a reliable transport it is TCP. protocol.
lr
Indicates that the element responsible for this resource implements the routing mechanisms specified in RFC 3261.
52
does this through what is referred to as the Offer/Answer model - which is little more than one party sending an initial query and then waiting for an answer from the other party. This walkthrough creates a simple console application that initiates a call with an correspondent, waits for a response, and then, optionally, acknowledges that response. The walkthrough is intended to show the steps needed to setup a SIP session.
<configSections> <sectionGroup name="konneticSettings" type="Konnetic.KonneticConfigurationSectionGroup, Konnetic.Signalling, Culture=neutral, PublicKeyToken=255449bd8f8c3771" > <section name="sip" type="Konnetic.Signalling.Sip.Advanced.Configuration.SipConfigurationSection, Konnetic.Signalling, Culture=neutral, PublicKeyToken=255449bd8f8c3771" requirePermission="false"/> </sectionGroup> </configSections> <konneticSettings> <sip> <!--The default SIP URI for the client-->
53
//Set the license key and initialise the SipCore Konnetic.Signalling.Sip.LicenseContainer.Key = "******PUT LICENCE KEY FROM EMAIL HERE******"; core = new SipCore(); 5. Inside the Start() method add the following code to create a new INVITE message. Optionally change the destination address passed into the CreateInviteRequest method.
//Create an Invite message. Use the factory method on the Invite object. //This method //relies heavily on the configuration to provide default values for the //message. InviteRequest invite = InviteRequest.CreateInviteRequest(new SipUri ("sip:bob@mel99.melbourne.com")); 6. The following code example shows how to register with a Request message to receive ResponseReceived events. Add it to the Start() method.
//Register to receive notification of responses invite.ResponseReceived += new EventHandler<ResponseReceivedEventArgs> (OnInviteResponseReceived); 7. Finally, add code to send the request and wait for user input
54
//Recieve a response to the INVITE request private static void OnInviteResponseReceived(object sender, ResponseReceivedEventArgs e) { if(e.Response.StatusClass == SipStatusClass.Successful) { if(e.Response.StatusCode == SipStatusCode.Trying){ //The other party sent us a Trying message to say the request got through and it is trying to establish a call. Console.WriteLine("===Trying==="); } if(e.Response.StatusCode == SipStatusCode.Ringing) { //The other party sent us a Ringing message to say the request got through and it is actively obtaining a response. Console.WriteLine("===Ringing==="); } if(e.Response.StatusCode == SipStatusCode.Ok){ //We got an OK. //Reply with an Acknowledgment InviteClientTransaction transaction = e.Response.Transaction as InviteClientTransaction; if(transaction!=null){ AckRequest ack = AckRequest.CreateAck((InviteRequest) transaction.OriginalRequest, e.Response.To.Tag); core.SendRequestDirect(ack); Console.WriteLine("===Sent ACK==="); } Console.WriteLine("===INVITE Success==="); } } else{ //INVITE failed. Console.WriteLine("===INVITE failed==="); Console.WriteLine("Reason: " + e.Response.StatusLine.ReasonPhrase); } } 2. Build the solution and run.
55
56
<configSections> <sectionGroup name="konneticSettings" type="Konnetic.KonneticConfigurationSectionGroup, Konnetic.Signalling, Culture=neutral, PublicKeyToken=255449bd8f8c3771" > <section name="sip" type="Konnetic.Signalling.Sip.Advanced.Configuration.SipConfigurationSection, Konnetic.Signalling, Culture=neutral, PublicKeyToken=255449bd8f8c3771" requirePermission="false"/> </sectionGroup> </configSections> <konneticSettings> <sip> <!--The default SIP URI for the client--> <defaultUserSipAddress uri="sip:alice@yourcompany.com" /> </sip> </konneticSettings>
//Declare the SIP library factored SIPCore class static SipCore core; 3. Add the following class declarations at the top of the body of the Program class. public static void Start(){ } 4. We first set the license key programmatically, then initialise the SipCore object in the Start() method.
//Set the license key and initialise the SipCore Konnetic.Signalling.Sip.LicenseContainer.Key = "******PUT LICENCE KEY FROM EMAIL HERE******"; core = new SipCore(); 5. Inside the Start() method add the following code to listen for incoming messages. Optionally change the local interface, port and transport protocol. //Start listening on the default local interfact on port 5060 for UDP messages only. core.StartListening(5060, TransportProtocol.Udp);
57
The following code example shows how to register to receive request message receipt events. Finally wait for user input.
//Register to receive request messages core.RequestReceived += new EventHandler<RequestReceivedEventArgs>(OnRequestReceived); //Make sure the main thread does not terminate Console.WriteLine("Press any key to finish."); Console.ReadLine();
//Handle newly arrived request messages static void OnRequestReceived(object sender, RequestReceivedEventArgs e) { SipRequest request = e.Request; if(request.Method == SipMethod.Invite) { Console.WriteLine("Invite Arrived"); //Accept if it is Bob, otherwise decline. if(request.From.Uri.UserName=="Bob"){ sipCore.SendResponse(new SipResponse(request, SipStatusCode.Ok)); } else { sipCore.SendResponse(new SipResponse(request, SipStatusCode.Decline)); } } else{ Console.WriteLine(string.Format("{0} Request Arrived", request.Method)); } } 2. Build the solution and run.
58
Introduction
This chapter describes the configuration of the SIP library. You will find information about the SIP library configuration parameters and how to set the parameters to suit your specific application requirements. The SIP library configuration is performed upon initialisation of the SipCore type. The format of the configuration files follows that of the standard .Net application config (http://msdn.microsoft.com/en-us/library/0hyxd0xc(v=VS.71).aspx) files. The SipCore takes as an overloaded constructor a Configuration object that you can use with Web configuration files, or non-standard deployments. The configSections specifies the Konnetic config section element and type.
<configuration> <configSections> <sectionGroup name="konneticSettings" type="Konnetic.KonneticSipConfigurationSectionGroup, Konnetic.Common" > <section name="sip" type="Konnetic.Signalling.Sip.Advanced.Configuration.SipConfigurationSection, Konnetic.Signalling" requirePermission="false"/> </sectionGroup> </configSections> <konneticSettings> <sip/> </konneticSettings> </configuration>
6.1 Runtime
Although it will be typical to configure the library using the application configuration, all configuration options are exposed using the SipConfiguration static object.
59
This config section details the the default SIP URI to use for a client's From URI. This value is used throughout the SIP library within the Request and Response factory methods. If this value is missing, then the factory methods will add an anonymous value into the From URI (e.g. "\"Anonymous\" <sip:anonymous@anonymous.invalid>"). The element name is defaultUserSipAddress. There is only one attribute: uri, containing the SIP URI of the default user. <konneticSettings> <sip> <!--The default SIP URI for the client--> <defaultUserSipAddress uri="sip:joe.b@contoso.com" /> </sip> </konneticSettings>
User Contacts
User contacts specify the alternate contact address for the user. Only SIP URIs are supported. The configuration section is a collection of URIs. If the section is missing, no alternate user contacts are specified. The element name is userContacts. There are no attributes. The element contains child elements. Use the add element with an attribute named uri to add new URIs to the UserContacts config section. <konneticSettings> <sip> <!--The (other) user contacts for the client, no user contacts are specified if empty--> <!--At least one contact should be a SIP URI--> <userContacts> <add uri="sip:joe.b@contoso.com" /> <add uri="mailto:joeb@gsip.com" /> </userContacts> </sip> </konneticSettings>
License
The License config section specifies the license key, type an registered name. Alternative mechanisms are available to provide the license key details are runtime including programmatically and via license files. The element name is license. There are three attributes. The type attribute must be set to "Konnetic.Signalling.Sip.License". The name attribute must be set to the registered name provided
60
ProxyServers
The ProxyServers config section allows the client application to configure the default outbound proxy servers for request messages. Alternative mechanisms are available to provide the proxy services, including on the SipCore. The proxy servers are used by the outgoing message processsors to create a route-set on the message (unless a route header field is already present). The processor calculates the remote address of the message according to RFC3261 and RFC3263 and takes into account the existiance of outbout proxy servers, Route header fields and loose routing rules. Passwords It is not recommended to store passwords in configuration files, although it is common. The SipCore provides a mechanism that you can use to add, edit and remove proxy servers <konneticSettings> <sip> <sipProxyServers> <add uri="sip:proxy1.com;lr" /> <add uri="sip:proxy2.com" realm="proxy1" username="username" password="password" /> </sipProxyServers> </sip> </konneticSettings>
61
User Agent
SIP allows a client to specify the type of machine it is using in the UserAgent header field. This config element specifies the user agent setting. If the element is missing, by default, no UserAgent will be specified. The element name is userAgent. There is one attribute: value. The attribute is a textural (UTF8) value indicating the agent type. <konneticSettings> <sip> <userAgent value="Softphone Beta1.5"/> </sip> </konneticSettings>
Supported Methods
SIP allows a client to specify the methods that it supports using the Allow header field. The config element name is supportedMethods. There is one attribute: methods. The attribute is a comma delimited list of upper-case method names. If the section is missing, the default is to specify the minimum required by RFC3261: INVITE, BYE, OPTIONS, REGISTER, CANCEL and ACK. <konneticSettings> <sip> <supportedMethods methods="INVITE,BYE,OPTIONS,CANCEL,ACK,MESSAGE"/> </sip> </konneticSettings>
Supported Scheme
SIP allows a client to reject a message based on the scheme. This config section specifies the scheme supported. The config element name is supportedScheme. There is one attribute: scheme. The attribute is a comma delimited list of lower-case scheme names. If the section is missing, the default is to specify sip and sips. <konneticSettings> <sip> <supportedScheme scheme="sip,sips"/> </sip> </konneticSettings>
62
SIP allows a client to specify that it understands certain extension and options using the Supported header field. This config section specifies the options supported. The config element name is supportedExtensions. There is one attribute: options. The attribute is a comma delimited list of lower-case options. If the section is missing, the default is to specify no supported extensions. <konneticSettings> <sip> <supportedExtensions options="100rel"/> </sip> </konneticSettings>
Supported Languages
SIP allows a client to specify that its content is intended for a particular natural language audience using the Content-Language header field. This config section specifies the default languages. The config element name is defaultLanguages. There is one attribute: languages. The attribute is a comma delimited list of case insensitive ISO-639 language abbreviations. If the section is missing, the default is to specify no content-language. <konneticSettings> <sip> <supportedLanguages languages="en-gb,de" /> </sip> </konneticSettings>
63
SIP allows a client to specify the acceptable media type of the message entity-body using the Accept header field. This config section specifies the default media types supported by the client. The element name is supportedMediaTypes. There are no attributes. The element contains child elements. Use the add element with an attribute named media to add new media types to the supported media types config section. If the section is missing, the default is to specify no mediatypes. <konneticSettings> <sip> <supportedContentTypes> <add media="application/sdp"/> <add media="text/html"/> </supportedContentTypes> </sip> </konneticSettings>
Required Extensions
SIP allows a client to demand that the other party support an extension using the Require header field. This config section specifies the default extensions demanded by the client. The element name is requiredExtensions. There is one attribute: options. The attribute is a comma delimited list of lower-case options. If the section is missing, the default is to specify no required extensions. <konneticSettings> <sip> <requiredExtensions methods="100rel"/> </sip> </konneticSettings>
<konneticSettings>
64
<sip> <!--The default transport protocol for the client, UDP is the default if empty--> <defaultTransportProtocol protocol="UDP" /> </sip> </konneticSettings>
Message Limits
The transport layer puts limits on certain internal message metrics. This primary reason is to prevent users and other parties from introducing poorly defined messages into the system. This may be to introduce security features that prevent harmful messages being processed. The following limits have been defined:
Limit Unit integer count integer count Default Description The maximum number of bytes allowed in the message body. The maximum number of SIP header fields on a message. The maximum number of bytes allowed for a header name. The maximum number of bytes allowed for a header value. The maximum number of parameters allowed on a header field. The maximum number of bytes allowed for whitespace in a header field.
maximumContentSize
5242880
maximumHeaderCount
256
1024
65537
maximumParameterCount
integer count
32
maximumWhitespaceSize
byte count
1024
The messageLimits config section specifies the default values. The element name is messageLimits . There is one attribute per limit. The attribute is a whole
65
<konneticSettings> <sip> <messageLimits maximumHeaderCount="100" maximumHeaderNameSize="512" maximumHeaderValueSize="4000" maximumParameterCount="20" maximumWhiteSpaceSize="100"/> </sip> </konneticSettings>
Timers
The transaction layer uses timers to control their behaviour. These timers can be configured. This primary reason is to optomise the library to conditions experienced by your environment. The timers and the configuration names are shown in the following table:
Timer ConfigName Default Value 500ms default Description
T1
TimerT1
RTT Estimate
T2
TimerT2
4s
The maximum retransmit interval for non-INVITE requests and INVITE responses Maximum duration a message will remain in the network INVITE transaction retransmit interval, for UDP only INVITE transaction timeout timer Proxy INVITE transaction timeout
T4
TimerT4
5s initially T1 64*T1 > 3min > 32s for UDP initially T1 64*T1
Generic INVITE transaction retransmit interval, UDP only Generic INVITE transaction timeout timer
TimerG
initially T1
66
Timer I
T4 for UDP
Timer J
Timer K
T4 for UDP
The element name is timers. There are no attributes. The element contains child elements. Use the add element with an attribute named key to specify the timer name, and attribute value to add the default value in milliseconds. If the section is missing, the default value shown in the above table is used. <konneticSettings> <sip> <timers> <add key="TimerT2" value="600"/> </timers> </sip> </konneticSettings>
67
Introduction
SipCore is an aggregate component which acts as a facade providing simplified views over the more complex but more powerful factored types, such as the HttpDigestAuthenticationManager, SipTransportLayer, SipTransactionStateManager and incoming and outgoing message processors which deal with parsing, Via header handling, address resolution, updating of state, and transmission management. This section deals with the basics necessary to write an application using the SIP library and the SipCore object, including:
Creation Destruction Event Processing Sending Messages Listening for Messages Configuration
7.1 Initialisation
7.1.1 Creation
Before performing any SIP-related activity, you must create and initialise a SipCore object. The SipCore performs the following:
Initialises a new SipTransportLayer object Initialises a new SipTransactionStateManager object. Initialises a new HttpDigestClientAuthenticationManager object. Parses any application configuration. Validates the license. Deserializes the SipConfiguration object.
68
7.1.2 Disposal
The SipCore object exposes a finalizer method. The Finaliser thread will initiate a disposal of all messages, transactions and listeners created using the SipCore object.
7.1.3 Properties
LocalAddressPort Used by the MessageTransmitter to specify on the 'Via' header field which end point the application wants the returned messages to be sent to (the 'sentby' property). An application may wish to provide a fully qualified domain name or an internet addressable IP address. If empty the default local IP address is used. ProxyServerCollection Specifies a pre-existing route set for any outbound messages. The ProxyServerCollection property can be set by applications to force a particular route set for the message. SecureProxyServerCollection Specifies a pre-existing route set for any outbound secure messages using TLS. The SecureProxyServerCollection property can be set by applications to force a particular route set for the message. Only SIPS addresses are allowed on the route-set for a secure message transmission. TransportLayer The SipTransportLayer which is managing the transmission of messages to and from the network on behalf of this SipCore. SipTransactionState The SipTransactionStateManager which is managing the transactional and dialog state on behalf of this SipCore. ClientCertificates TLS message transmission requires clients to provide a certificate to the server for mutual
69
A value indicating whether the SIP library should seperate multiple-valued headers onto seperate lines where possible. HeaderNameFormat A value indicating whether the SIP library should use compact header field names by default.
UseAdditionalDnsRecords
AllowFramingOnSingleNewLine
SupportIPv6Dns
70
UseHttpDigestIntegrityAuthentication
The library contains sophisticated Authentication management routines. Message integrity can be provided using the Digest Auth-Int mechanism. The default behaviour is to support authentication only, use this flag to also support integrity.
The library validates incoming messages against the RFC3261 standard on a relaxed basis by default. This entails checking for the presence of mandatory fields and properties required for further processing. Use this ExtendedValidationOfIncomingMessages flag to increase the validation behaviour of the library and send automatic responses to some standard validation failures. The validation makes heavy use of the SIP configuration. The library parses incoming messages and validates them against the RFC3261 standard. Any exceptions are caught and housed in the ParseExceptions (SipAggregateExceptions) property on the SIP Message. The library is relaxed by default and does not automatically throw these exceptions. Use this flag to conveniently throw any exceptions on first access to an instance member of the SIP Message. RFC3261 describes a sophisticated call management routine. SIP DNS resolution can result in an ordered list of address, port, transport tuples to try. Only when the previous tuple fails (failure is defined as either a transport error or transaction timeout) does the next tuple get attempted. This can result in the same message being sent many times (each transaction will also retransmit the message a number of times). Use this flag to disable call managment and only rely upon the transaction retransmission to the first (preferred) tuple.
ThrowOnParseExceptions
DisableCallManagement
71
CertificateValidation
ClientTransactionCreated
Occurs when a connection is created. ConnectionCreated Connections can be created when the user client begins to listen for requests and a recipient initates a transmission or when the user client sends a message to a new recipient. Occurs when a connection is dropped or forcably terminated. This occurs at timeout or because the other side dropped the connection. Occurs when data is received at the transport layer. Occurs when data is sent at the transport layer.
ConnectionDisposed
DataReceived DataSent
Occurs when a dialog is created. DialogCreated In the standard SIP implementation Dialog's are created on reciept of a successful response to an INVITE. Occurs when a listener aborts its operation. Occurs when there is a failure in the message processing. Occurs when the transaction failed to send a message. Occurs when a request is received from the transport layer. Occurs when a response is received from the transport layer. Occurs just before a request is sent and gives the user client an opportunity to cancel the transmission. Occurs just before a response is sent and gives the user client an opportunity to cancel the transmission. Occurs when a server transaction is created in response to receipt of a new request.
SendingRequest
SendingResponse
ServerTransactionCreated
72
TransportFailure
Occurs when a message is received and the processing fails in the transport layer or when there is an asyncronous send failure. The event is fired when the transport layer cannot frame the message, or the message does not obey standard framing and basic parsing rules (e.g. lack of Content-Length field in TCP transports or missing CRLF at the end of a header field). Framing is the process of identifying discrete messages within a stream such as a TCP network stream. Occurs when an unmatched request is received from the transport layer. The event is fired when a CANCEL message is received that does not match any existing transaction. This is typically due to a recipient attempting to end a session with this user client where the transaction has timed out. Occurs when an unmatched response received from the transport layer. Occurs when the library is validating the request. Allows user client to cancel validation and/or send a response. Occurs prior to when the library validates the response. Allows the user client to authenticate the response and cancel validation, further processing and/or send a response.
UnmatchedCancelReceived
UnmatchedResponseReceived
UserRequestValidation
UserResponseValidation
The following code demonstrates how initalises the core, start listening for incoming messages on interface "124.191.1.8:5060" and print out the reason phrase to the console on creation of a new Server Transaction. C#: Register to receive notification of incoming messages using System; using System.Net; using Konnetic.Signalling.Sip; ... //Initialise SipCore core = new SipCore(); //Start Listening on IP 124.191.1.8 with the default SIP port of 5060. core.StartListening(new IPEndPoint(IPAddress.Parse("124.191.1.8"), 5060)); //Register to receive notificaton of new messages and print the Reason Phrase to the console core.ServerTransactionCreated += delegate(object sender, TransactionEventArgs e) { Console.WriteLine(e.Transaction.MostRecentResponse.StatusLine.ReasonPhrase);
73
74
75
Alternatively, the following code demonstrates sending the same message directly to "124.191.8.8" using TCP. C#: Send an Invite using System; using System.Net; using Konnetic.Signalling.Sip; ... //Initialise SipCore core = new SipCore(); //Create an Invite message. Use the factory method on the Invite object. This method relies heavily on the configuration to provide default values for the message. InviteRequest invite = InviteRequest.CreateInviteRequest(new SipUri ("sip:bob@mell99.melbourne.com")); //Create a destination for the message. DestinationTuple destination = new DestinationTuple("124.191.8.8", 9000, TransportProtocol.Tcp); //Send the message core.SendRequest(invite, destination);
76
77
The SIP library provides a flexible API for working with SIP messages and message parts such as headers and addresses. The Message API provides functions for working with the following objects:
Header objects:
Accept AcceptEncoding AcceptLanguage AlertInfo Allow AuthenticationInfo Authorization Body CallId CallInfo Contact ContentDisposition ContentEncoding ContentLanguage ContentLength ContentType CSeq Date ErrorInfo Expires
MaxForwards MimeVersion MinExpires Organization Priority ProxyAuthenticate ProxyAuthorization ProxyRequire RecordRoute ReplyTo Require RetryAfter Route Server Subject Supported Timestamp To Unsupported UserAgent
78
8.1 SipMessage
The SipMessage object manages the collection of Header Fields, content, parsing exceptions and managing transaction. It is used to construct stand alone messages or represent messages received from the Transport Layer. It is an abstract class with two concrete derived classes:
Response Request (base class of InviteRequest, OptionRequest, RegisterRequest, AckRequest, ByeRequest, CancelRequest, InfoRequest, UpdateRequest, MessageRequest types)
The SipResponse and SipRequest classes contain all the message parts, including the message start line, one or more header fields and an optional message-body. The SipMessage API functions can be categorised as follows
Constructors Header Fields and functions Encoding and Parsing Functions Owning Transaction Parsing Exceptions
79
Because of this side-effect with the MultiValued properties, the debugger will dirty the debugging process when accessing any property to display the value in the IDE. For this reason, the SipMessage derived objects have their DebuggerTypeProxy attribute set. The proxy displays only the header fields present, the first line, transaction and exception properties. Access to the underlying type can be obtained during debugging by accessing the base set property.
80
81
82
Internally the string conversion uses parsing and string encoding. Parsing can be orders of magnitude slower than direct assignment of properties. The following code demonstrates how to get and set parameters in a To header field using each pattern: C#: Working with Header properties static void WorkingWithHeaders(){ //Use constructors to set the value of the URI on the TO header field ToHeaderField to = new ToHeaderField("sip:bob@melbourne.com"); //Use properties to set and get header field parameters to.DisplayName = "Bob The Builder"; Console.WriteLine(string.Format("{0} is at {1}",to.DisplayName,to.Uri.ToString())); //Use string conversion to set and get header field parameters to = "bob <sip:bob@sydney>"; Console.WriteLine((string)to); }
83
There are two types of functions you can use to insert headers into messages. The function type you choose will depend on the headers you wish to insert. The function types you may use are as follows:
Properties - for well-known (i.e. non-extension) header fields, properties are provided. Addition methods - for all types of headers, Add and Insert methods are provided.
C#: Adding and Removing Header Fields static void AddAndRemoveHeaderFields() { //Create a new header field ContactHeaderField contact = new ContactHeaderField(new SipUri ("sip:bob@melbourne.com"), "Bob"); //Creat a new Invite request message InviteRequest i = InviteRequest.CreateInviteRequest(new SipUri ("sip:bob@melbourne.com")); //Add the field to the message i.AddHeader(contact); //Check if the Contact header exists, if so, remove it if(i.ContainsHeader(ContactHeaderField.LongName)){ i.RemoveHeader(ContactHeaderField.LongName); } }
8.4 Headers
8.4.1 Header Fields
The header fields are managed via properties. They can be either multi or single valued. Multivalued header fields are contained within a MultiValued collection, with each item representing a header field value for a particular header field type. Single valued header fields are represented by
84
8.4.2 MultiValued<>
Multi-valued header fields are those fields that may occur more than once in the message. They can be formed on separate lines, or on a single line separated by token (usually a comma). These header fields are treated as a read-write collection and returned in a read-only property. You can distinguish between the header collection properties as their names all end with "Headers". The following code block show an example of working with the MultiValued. We first create a new SipMessage using the derived Invite class, we then add a new Accept-Encoding value; insert a new Accept-Encoding value; check if "gzip" exists in the collection, and if so, remove it. Working with MultiValued static void WorkWithSipMessage(){ InviteRequest i = InviteRequest.CreateInviteRequest(new SipUri ("sip:bob@melbourne.com")); // Add a new value to the AcceptEncoding header field collection. i.AcceptEncodingHeaders.Add(new AcceptEncodingHeaderField("gzip")); //Insert a value at the end of the collection. i.AcceptEncodingHeaders.Insert(1, new AcceptEncodingHeaderField("x-zip")); //Remove 'gzip' if the collection contains the value if(i.AcceptEncodingHeaders.Contains("gzip")){ i.AcceptEncodingHeaders.Remove("gzip");
85
SIP headers that do not have a dedicated object in the SIP message, called Extension Headers, are stored in the SipMessage header collection.
8.4.4 Parameters
Many header fields will adhere to the general form of a value followed by a semi-colon separated sequence of parameter-name, parameter-value pairs. Even though an arbitrary number of parameter pairs may be attached to a header field value, any given paramter-name must not appear more than once. Parameters are segregated in the SIP library into well-known and extension parameters. Well-known are expected and validated, extension parameters are simple are generally not known to the SIP library and follow the name/value form, where the name is a token (alphanum + unreserved ASCII marks) and value is a token or quoted UTF8 string.
86
SIP provides a mechanism for representing header field names in a compact form. For example, the header, "from: Bob <sip:bob@melbourne>" will become "f: Bob <sip:bob@melbourne>" when compact form is used. The following table represents the headers that can accept compact form and the corresponding compact form for each header.
Long Name Compact Name a c e f i k l m s t v
Accept-Contact Content-Type Content-Encoding From Call-ID Supported Content-Length Contact Subject To Via
87
88
A SIP transaction comprises all messages sent within a message exchange. Specifically a transaction consists of an initial request and any responses to that request. The Transaction API of the SIP library contains a set of methods and events 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 Dialog. An example of such a transaction is one that handles an OPTION request. Using the Transaction API, you can create and initialize a transaction and control a transaction according to the transaction state. You can create a transaction with any method (except ACK). The second purpose of the Transaction API is for writing a SIP server. Using the Transaction API, you can implement a Proxy server, Redirect server and Registrar. You can receive incoming requests and decide whether to redirect or proxy the request according to the request method and the transaction state. Using these functions, you can fully implement both stateless and stateful proxies.
9.1.1 Transactions
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. A transaction is a stateful object, which can assume any state from a set defined in the Transaction API. The Transaction state machine represents the state of the transaction between the client and the server.
An Invite transaction also includes the ACK request when the final response to the Invite request is non-2xx.
89
Transactions represent the state of the transaction between client and the server. Thus transactions are divided into:
Furthermore, in the case of a transaction where the original request was an INVITE the transactions is known as an InviteTransaction. These transactions are distinguished from all other general transactions, referred to as GenericTransaction. Thus the state machine is divided into the following parts:
9.2.1 Properties
The following properties are available on all transactions: Method Specifies the method of the SIP request. For client transactions, you supply the method when sending the initial request. For server transactions it is the method of the initial request that was received.
90
MostRecentResponse Returns the most resent response sent or received by the transaction. OriginalRequest Returns the original request message that initiated the transaction. RecipientEndPoint Returns the end point for the recipient of the transaction's transmissions. TransactionState Represents the state of the transaction between the client and the server.
9.2.2 InviteServerTransaction
The following property is only available on the InviteServerTransaction: BlockTrying Blocks the automatic sending of a Trying message from this transaction upon receipt of an INVITE. Otherwise the transaction will automatically send a Trying message back to the correspondent.
9.3 Methods
9.3.1 SendResponse
Use this instance method to send a provisional or final response to a transaction that received an incoming request. You can use this method with any response code and reason phrase. The following code demonstrates a response to receiving a BYE request. C#: Acknowledging a BYE request //Server transactions handle incoming Requests. //This example handles the BYE request. private static void OnServerTransactionCreated(object sender, TransactionEventArgs e) { ServerTransaction trans = (ServerTransaction)e.Transaction; if(trans.OriginalRequest.Method == SipMethod.Bye) { Console.WriteLine("===BYE Received===");
91
9.3.2 SendCancel
Use this method to cancel a transaction that reached the Proceeding state. You can use this function only on INVITE client transactions. You supply this function with the transaction you wish to cancel. A CANCEL transaction will be created and a CANCEL request will be sent to the remote party.
9.3.3 StopTimers
Use this method to halt transactional timers firing. This can be useful when debugging.
9.3.4 RestartTimers
Use this method to restart transactional timers firing again after stopping them. This can be useful when debugging.
9.3.5 TerminateAndDispose
Use this method to cause an immediate shut-down of the transaction. A transaction is a selfterminated object. The termination of a transaction depends on the transaction state and timer configurations. By using this function, the application can terminate a transaction before its normal termination. After calling this function, the transaction will assume the Terminated state.
9.4.1 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 SendRequest, SendResponse,
92
9.4.2 Terminated
This is the final state of the transaction. When a transaction is terminated, the transaction assumes the Terminated state. Upon reaching the Terminated state, you can no longer reference the transaction and it will be disposed.
9.4.3 Trying
After calling SendRequest() with a method other than INVITE, which generates and sends a Request message, the transaction enters the Trying state. The client transaction remains in this state until it receives a provisional or final response from the server. Receipt of a provisional response will cause the transaction to assume the Proceeding state. Receipt of a final response will cause the transaction to assume the Completed state. While in the Trying state, the transaction retransmits the request message according to the rules defined in RFC 3261, and the values configured for T1, T2 and timer F. The retransmissions take place only if the transport is an unreliable transport (UDP). If no response is received when Timer F expired, the transaction is terminated automatically and assumes the Terminated state (in any transport).
9.4.4 Proceeding
Upon receipt of the first provisional response by a client transaction (not a retransmission), the transaction assumes the Proceeding state. The transaction will continue to retransmit the request message until the Timer F expires using a consistent interval of T2 seconds as defined in RFC 3261 (only if the transport is unreliable (UDP)). Receipt of a final response will move the transaction to the Completed state. If no final response is received when the Timer F is expires, the transaction is terminated and assumes the Terminated state.
9.4.5 Completed
Upon receipt of a final response, the transaction assumes the Completed state. When entering this state, a transaction timer is set to T4 if the transport is an unreliable transport. When T4 expires, the transaction is terminated and assumes the Terminated state. If the transport is a reliable transport, no timer is set and the transaction is terminated and assumes the Terminated state immediately
93
9.4.6 Trying
Upon receipt of a request (that is not a retransmission) by a server transaction, the transaction assumes the Trying 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.
9.4.7 Proceeding
When calling SendResponse(), the transaction generates and sends a response message. If the response is Informational the transaction will then assume the Proceeding state.
9.4.8 Completed
When calling SendResponse(), the transaction generates and sends a response message. If the response is not Informational the transaction will then assume the Completed state. When entering this state, a transaction timer is set to Time J if the transport is an unreliable transport (i.e. UDP). When this timer expires, the transaction is terminated and assumes the Terminated state. If the transport is a reliable transport, the transaction is terminated and assumes the Terminated state immediately when it reaches this state.
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
94
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).
9.4.10 Proceeding
Upon receipt of the first provisional response by a client INVITE transaction,the transaction assumes the Proceeding state. When entering this state, a transaction timer is set to provisional Timer. When this timer expires, the transaction is terminated. Receipt of a final response in the Proceeding state will move the transaction to Completed state.
9.4.11 Completed
Upon receipt of an INVITE final response, the transaction assumes the Completed state. If the response is a 2xx response, the transaction will then assume the Terminated state. If the response is a non-2xx response, the application should initiate the ACK request by calling the SendAcknowledgement() method. After sending the ACK, the transaction will move to the Completed state.
9.4.13 Completed
When calling SendResponse() on an INVITE transaction, the transaction generates and sends a response message. The transaction will then assume the Completed state. For a non-2xx response, the transaction retransmits the final response according to RFC 3261, and the value configured for T1 and T2. The retransmissions take place only if the transport is an unreliable transport (i.e. UDP). If no ACK response is received when 64*T1 timer (Timer H according to RFC 3261) expires, the transaction is terminated automatically and assumes the Terminated state (unless the state has changed). If an ACK message is received, the transaction moves to the Confirmed state. For a 2xx response, the transaction sets the Timer I after sending the 2xx response. The transaction terminates
95
9.4.14 Confirmed
When entering this state (the transaction received an ACK message), a transaction timer is set to T4 if the transport is an unreliable transport (i.e. UDP). When T4 expires, the transaction is terminated and assumes the Terminated state. If the transport in a reliable transport, no timer is set and the transaction is terminated and assumes the Terminated state immediately when it reaches this state. (Timer I as defined in RFC 3261).
9.5 Timers
SIP transactions make extensive use of timers to control their behaviour. The following table lists the most common timers:
Default Value 500ms default
Timer
ConfigName
Description
T1
TimerT1
RTT Estimate
T2
TimerT2
4s
The maximum retransmit interval for non-INVITE requests and INVITE responses Maximum duration a message will remain in the network INVITE request retransmit interval, for UDP only INVITE transaction timeout timer proxy INVITE transaction timeout
T4
TimerT4
5s initially T1 64*T1 > 3min > 32s for UDP initially T1 64*T1
non-INVITE request retransmit interval, UDP only non-INVITE transaction timeout timer
Timer
TimerG
initially T1
96
TimerH
64*T1
Timer I
T4 for UDP
Timer J
Timer K
T4 for UDP
The table also shows the configuration name given to the timer. See the configuration section later for implementation details.
97
The authentication mechanism enables User Agent Clients to prove their identity (client authentication) to servers and proxies which require authentication. In turn the mechanism supports the ability of the server to prove its identity (mutual authentication). Furthermore, message integrity can be established with the use of integity functionality (Auth-Int Quality of Service). The SIP Library supports SIP authentication using the HTTP Digest Scheme as described in RFC3261 and RFC2617. The HttpDigestClientAuthenticationManager object is responsible for applying the authentication mechanisms described in the RFCs and manage both client and server authentication processes.
10.1 Overview
The basic concept of the authentication mechanism is the shared secret between client and server or proxy. Prior to establishing SIP communication, the client should obtain a username and password (Credentials) that the server acknowledges. In addition a domain or realm should be provided, the realm is a string to be displayed to users so they know which username and password to use. The password is the shared secret between the client and the server. The Digest Authentication method implemented by the SIP library used the MD5 algorithm in the authentication process. MD5 is a one-way hash function that operates on a given string and produces a fixed length hash value. The Sip Library hashes certain information, including the password, username and realm, and includes the hash as the Response value in any authentication exchange when prompted by a Challenge. A SIP server will verify the clients authenticity using the HTTP Digest Scheme as follows: 1. A server responds to the originator of an incoming request with a 401 Unauthorised response. A Proxy server responds with the 407 Proxy Aithentication Required response. These responses each include special Authentication headers with infomation required by the client in the Authentication process. Within a 401 the header is WWW-Authenticate, and within a 407 it is ProxyAuthenticate. The information included in the Authentication header is called the Challenge. 2. A client uses the Challenge parameters and the user Credentials to generate a hash value using the MD5 algorithm. 3. The hash value and certain other proeprties, such as a one-time ClientNonce (opaque 32
98
dimensioned random hex array) are included inside an Authorization or ProxyAuthorization header field. The header field is added to the original request message that was challenged. 4. The client retransmits the request message. 5. The server uses the hashed value in the Response property of the (Proxy)Authorization header field to verify the authenticity of the originator by hashing the same information using the MD5 algorithm and comparing hashes. The process of receiving a challenge and sending credentials is refered to as an exchange. Integrity HTTP Digest can provide for message integrity if both parties support it. Authentication with message integrity can be used if the 'auth-int' flag is provided on the quality of protection (QoP) property of the challenge. Client applications can request message integrity be used by setting the SupportAuthenticationIntegrity property of the HttpDigestAuthenticator static class. In this mechanism, the message body (the whole body excluding the initial (CRLF)CRLF seperator combination) is hashed along with the credentials.
10.1.1 Authenticator
99
mechanism on incoming and outgoing messages. However, client applications can independently access the MD5 and HTTP Digest algorithms via the static HttpDigestAuthenticator class.
100
The SipCore and the HttpDigestClientAuthenticationManager on the SipCore both expose the AuthenticaionChallengeReceived event. The event is fired when a message is received containing a challenge. The event argument object, ChallengedReceivedEventArgs, contains a property indicating whether the challenge should be meet with an auto response (AutoRespond). During auto response, a set of credentials are found for each realm/domain challenging. Authorization headers are added to the original request message, and the message's CSeq sequence number is incremented. Finally the request is resent.
101
102
Transport Layer
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, using both IPv4 and IPv6 addresses. Or using authentication and encryption using TLS. However, TLS is still carried via TCP. TCP and UDP differ in many ways. The most fundamental difference is that UDP is connection-less, while TCP are connection-oriented and therefore create a reliable data transfer service. The SIP library supports UDP datagrams and TCP connection-oriented transports. This section explains how to maintain a persistent connection and how to use the TCP and UDP transports with the SIP library API. In addition, this chapter describes the abilities that the SIP library provides for monitoring buffers that are sent or received from the sockets.
11.1.1 Sockets
The SIP library uses asynchronous non-blocking sockets. The result of using non-blocking sockets is that the sending of messages can be completed after the API call has returned. For example, a call to Send() on the TransportLayer object may return before the bytes are actually queued up in the network infrastructure, and before being pushing onto the physical layer. The SIP library will manage the sending operation until it is complete.
103
In many cases a single Connection may be used for different messages, transactions or dialogs. Opening and closing connections is often not desirable because of the extra messaging overhead. RFC3261 encourages connection persistency, which is the reuse of an open client connection. The feature of the SIP library add the capability to identifying that a message can be sent on an existing open connection. The message is then sent using this connection. Connections can be used for client or server purposes. Connection Persistency referes to a technique in which connection information and configuration is persisted to disk and provides a robust failover mechanism. The Unity SIP Library does not provide this functionality.
11.1.3 Lifetime
Each connection manages its own lifetime.
For connection-oriented protocols (TCP and TLS) connections will dispose if the far side disconnects.
The connection timeout fires. The timeout is governed by the connectionInactivityTimeout attribute of the transportLayer configuration element. The timeout can also be changed on each individual Connection object.
An exception in the processing of incoming or outgoing transmissions may disconnect the connection.
104
A Connection is opened from a specific local endpoint and specific remote endpoint using one type of transport protocol. The LocalEndPoint and RemoteEndPoint indicate these network interfaces. A System.Net.IPEndPoint is used to contain the invariant. The IPEndPoint contains an IPAddress and Port value. The two endpoints along with the Transport protocol provide the Connection key used in the ConnectionPool. Transport Indicates whether the connection is a TCP or UDP connection. The transport is part of the SipConnection key used in the SipConnectionPool. Direction Indicates the transmission direction which initiated this connection. Whether the connection was started by a client or server activity. LastTransmissionTime The timing of the last transmission to or from this connection
105
ephemeral port number. The SIP protocol includes mechanisms which ensure that responses to a request reuse the existing connection, and ports, if available. However, this works both ways between two entities. With each using an ephemeral port number to send the initial request message. This frequently causes a pair of SIP entities to use one connection for requests and responses in each direction. The following figure illustrates the connection establishment of two requests one originated in each agent.
106
RFC3261 recommends that connection should be kept open for a period of time after the last messge was exchanged over the connection. However, the exact time period to leave the connection open is not defined and is implementation specific. This means connections can build up inside the connection pool. To manage the size of the connection pool the Unity SIP Library uses the maximumConnectionPoolCount configuration value which determines the recommended number of opened connections that the SIP Library is allowed to hold at any given moment from its pool of connections. When the limit is reached connection pruning takes place, with a percentage of the oldest connections being disconnected and disposed.
11.2.5 Timeout
A inactivty timeout is available for each connection. Once the timeout fires the connection is disconnected, disposed and removed from the connection pool.
Guarantees the identity of a remote computer. Transmits messages to that remote computer in a secure encrypted manner.
TLS uses pairs of asymmetrical encryption keys to guarantee the identiy of a remote computer. The public key of each remote computer is published in a certificate. A certificate is a document digitally signed by a certifcate authority that both sides of the connection agreed to traust before the TLS connection establishment has stared. (VeriSign and Thawte are examples of such vertificate authorities). In the TLS connection establishment process, the certificate of the remote computer is retrieved and verified and a new key and encryption algorithm is negotiated for the specifiec connection.
11.3.1 Establishment
TLS connection establishment requires the completion of the following three phases:
107
Phase 1: TCP Connection Establishmentas 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.
Phase 2: TLS Handshakethe basic TLS handshake process consists of several TCP messages which go from client to server and from server to client, in which the client retrieves the servers certificate, verifies it, negotiates an encryption key and algorithm for the session, and both parties make sure that the security of the handshake has not been compromised. For more information on the TLS handshake see RFC 2246 and RFC 3546.
Phase 3 (Optional):Mutual AuthenticationThe server may request the client authenticates during the process and demand client certificates be provided in the certificate exchange
Phase 4: ValidationIn this phase, the client makes sure that the certificate handed to it by the server does indeed belong to server. This step is taken to prevent the situation in which a server named malise.com will present a valid certificate of someonelse.com.
After these phases have been completed, encrypted messages can be transmitted on the connection in a secure manner.
108
The TransportLayer of the SIP library is a low-level API. It provides several events that can be used to inspect and control the buffers that are sent or received by the sockets controlled by the SIP library. The events are implemented for all transport protocol types - TCP or UDP. The buffers contain encoded SIP messages. Each message will contain header fields that may have unique encoding specifications, consult each header field documentation for information. To get the events, and application registers to the event.
CertificateAuthenticationFailure Occurs when when SSL certificate authentication fails. Occurs when a server attempts to authenticate a certificate with this library and allows a listening client to validate the certificate. Occurs when a client requests a certificate from this library. Occurs when a server requests a certificate from this library. Occurs when a connection is created.
CertificateValidation
109
ConnectionRefused
Occurs when a connection is refused. Typically this is because the pool is full. Occurs when data is received from a connection. The message has been framed but not yet parsed or processed. Occurs when the transaction failed to send a message.
DataReceived
MessageSendFailure
The following code demonstrates how to initalise the core, start listening for incoming message on interface "124.191.1.8:5060" and print out the recipient information, and data parameters when a new message arrives. C#: Register to receive notification of incoming messages using System; using System.Net; using Konnetic.Signalling.Sip; using Konnetic.Signalling.Sip.Advanced; ... //Initialise SipCore core = new SipCore(); //Start Listening on port 5060 using TCP and UDP. core.ListenForConnections(5060)); //Register to receive notficiaton of new data and print out who sent the data, how many header fields are contained in the message, and the length of the content core.Transport.DataReceived += delegate(object sender, DataReceivedEventArgs e) { Console.WriteLine("From: " + e.Sender.HostPort); Console.WriteLine("HeaderField Count: " + e.Data.HeaderFields.Count); Console.WriteLine("Content Length: " + e.Data.ContentLength); };
11.5 IPv6
Working with IPv6 Addresses
IPv6 (Internet Protocol Version 6) is the "next generation" protocol designed by the International engineering task Force (IETF), the Internet standardisation body, to replace the current internet protocol, IPv4. IPv6 overcomes a number of problems in IPv4, such as the limited number of available IPv4 addresses. It also adds many improvements to IPv4 in areas such as routing and network auto-configuration. IPv6 is expected to gradually replace IPv4, with the two coexisting for a
110
number of years during a transition period. The most significant change is that IPv6 supports an address scheme that uses 128 bit address space compared with the 32 bit IPv4 address. The SIP Library enables an application to work with the IPv4 IP Stack, IPv6 IP Stack or dual stacks. Supporting the IPv6 scheme affects the low-level services needed from the operating system as well as message and headers syntax. It does not affect the way SIP works with transactions or dialogs or other objects. In IPv6 addresses there are eight groups of four digits each. The hexadecimal number system is used for the digits. Thus, each group occupies 16 bits of space and the entire address represents (but does not always require) 128 bits. For example, 3ffe:6a88:85a3:08d3:1319:8a2e:0370:7344. is a valid address. If a 4 digit group is 0000, it may be omitted, thus in the syntax of IPv6, 3ffe:6a88:85a3:0000:1319:8a2e:0370:7344 is the same as 3ffe:6a88:85a3::1319:8a2e:0370:7344. Following this rule, if more than two consecutive colons result from this omission, they may be reduced to two colons, as long as there is only one group of more than two consecutive colons. Thus, all the following addresses are valid and have the same meaning,
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.
111
The layer can also be used to send and receive messages directly, thereby bypassing the transaction layer.
11.6.1 TransportDataBuffer
The Transport Layer returns a TransportDataBuffer container in the DataReceived event. The buffer contains:
A collection of HeaderFieldDataBuffer objects in the HeaderFields property. A byte array containing the message content. Two field indicating the content length.
The HeaderFields collection is an ordered list of the CRLF separated bytes received off the network wire. The first item in the collection will be with the Status Line for a Response message, or the Request Line for a Request message. The HeaderFieldDataBuffer container for the first line only includes the Value byte array, the Name byte array is missing. Each following item is an unprocessed object containing the byte array of the field Name, and field Value. The message content beyond the SIP header fields is contained within the Content byte array. Finally, two fields show the content length. They are derived from two sources, firstly the ContentLength is the actual length of the content byte array. Secondly the ContentLengthHeaderFieldValue is the value shown in the ContentLength header field.
112
static void Transport_DataReceived(object sender, DataReceivedEventArgs e) { TransportDataBuffer db = e.Data; Collection<HeaderFieldDataBuffer> buffer = db.HeaderFields; Console.WriteLine(string.Format("SIP message received with {0} lines and with a content length of {1}.", buffer.Count, db.ContentLength)); HeaderFieldDataBuffer buf = buffer[0]; char[] chars = Encoding.UTF8.GetChars(buf.Value); Console.WriteLine(string.Format("First line: ", new string(chars))); }
11.7 Example
Listening for and Sending Messages Directly
Once the SipCore is initialised we have to manually start listening for incoming messages. The following example illustrates the mechanism to listen for incoming messages and registering to receive notification on receipt of an new Request message. C#: Listen for Messages Directly
static SipCore core; static void SendResponseDirectly() { //1. Initialise, listen and register for the RequestReceived event core = new SipCore(); core.Transport.ListenForTcpConnections(new IPEndPoint(IPAddress.Loopback, 5060)); core.RequestReceived += new EventHandler<RequestReceivedEventArgs> (core_RequestReceived); }
The next code block sends a response to the receipt of the message. In this example, if the message is
113
an Invite, a Ringing message is returned, to indicate the User Agent is trying to get the attention of the user. C#: Respond to an Invite with a Ringing message static void core_RequestReceived(object sender, RequestReceivedEventArgs e) {
//2. Create the response message, which in this instance only allows INVITE messages. SipResponse response = null; if(e.Request.Method == SipMethod.Invite){ response = new SipResponse(e.Request, SipStatusCode.Ringing); } else { response = new SipResponse(e.Request, SipStatusCode.MethodNotAllowed); } //3. Send the response directly bypassing the transaction layer using the DestinationTuple from the response message. core.Transport.Send(response.GetBytes(), response.Recipient); }
114
SIP uses DNS procedures, laid out in RFC3263, extensively during normal operation in order to allow clients and servers to resolve SIP URIs to an ordered list of IP Address, port, and the transport protocol of the next hop to pass the message to. The Unity SIP library's DNS features are implemented in the SipDnsCache and SipDnsFacade, and are utilised in the outgoing message processors that deal with sending Request and Response messages prior to actual transmission using the Transport layer. The DNS query implementation is blocking, lazy and contains blacklists. That is, outgoing messages are not put on a seperate thread, but only the DNS queries necessary to accomplish the next successful send operation are performed at any one time. In addition, blacklists of previously failed DNS queries are kept for NAPTR and SRV DNS queries. Queries on the blacklist are not performed again. The DNS functionality includes:
A/AAAA queries resolve IP IPv4/IPv6 address respectively, given a domain/host string. SRV queries resolve the location (domain/host and port) of SIP services. NAPTR queries resolve a SIP target (Request-URI, Route URI or SentBy value) to a prioritised list of supported SIP services.
The result of the usage of NAPTR, SRV, A and AAAA DNS queries is a list of resolved addresses, ports and transports that the library is able to try one after the other, in case of a send failure. The Unity SIP Library only supports DNS queries over UDP. The client application call stack must have the permission to access the DNS servers on the network to perform DNS queries.
12.1 Implementation
12.1.1 When DNS is Used
If the target host text (see below) for a request is an IP Address then that is used in the first instance, otherwise DNS queries are required to resolve the host text to a transport protocol, IP Address and port.
115
For response messages where the request was sent via a reliable transport (e.g. TCP), the inbound connection is used, if still open. Otherwise the top-most Via header field's received parameter alongside the port from the SentBy parameter is used. Finally DNS queries are required to resolve the host text. When the response uses UDP. The multicast address on the top-most Via header alongside the port from the SentBy parameter is used in the first instance. If that is not present, or fails, the top-most Via header field's Received parameter alongside the port from the SentBy parameter is used. Finally, if that is not present, or fails, DNS queries are required to resolve the host text.
12.1.3 Caching
The Unity SIP library is configured to support DNS caching. Positive DNS answers are kept in the caching module for further usage. Negative NAPTR and negative SRV querys are also kept in a blacklist that can be access via the SipDnsFacade class.
NAPTR: used to determine the transport and services locations and their respective preferences. SRV: used to determine the port and the service host. A and AAAA: used to determine the IPv4 and IPv6 addresses for a specific host.
116
The combination of the three types of records creates a hierarchy of results and DNS records, as illustracted in the following figure. Each NAPTR query can return several SRV records, which, in turn can result in serveral host records, each with several IP addresses (A/AAAA records). Each IP Address is tries in turn untill a sucessful transmission of the message. The SIP library is designed to issues the minimum number of DNS queries in order to sucessfuly transmit the message. So, if the message is transmitted using the first A query from the first SRV query from the first NAPTR query, other queries are not issued.
117
A DNS query may return more than the immediate result in what are known as Additional Resource Records. These may be used to reduce the overall number of DNS queries needed. However, implementers should consider that there have been instances of DNS poisoning with the use of Additional Resource Records. Each additional resource record can contain the next SRV, A and AAAA records, thereby bypassing the need to query for them. In addition, there is no guarentee that all the possible SRV, A, and AAAA records will be returned in the Additional Resource Record. The Unity SIP Library does not issue further DNS queries once the IP addresses in the Additional Resource Record have been exhausted.
118
The use of Additional Resource Records in DNS queries can be turned off or on using the Behaviour static property on the SipCore object.
119
120
121