Ozeki VoIP SDK - Product Guide
Developers Guide
Deprecated Content
Source code explanation for building a C# SIP softphone client that can register with a SIP service provider
This page provides information about how to build a C# SIP softphone client that can register with a SIP service provider.
| Ozeki
C# SIP softphone client example can be obtained by clicking the download link below: Download Ozeki C# SIP softphone client example! |
The communication devices of SIP – SIP messages
SIP messages are text messages defining UTF-8 encoded requests and responses in client-server communication. Both message types are based on the same form. Each SIP messages consist of a start-line and one or more message headers, then one empty line (CRLF) that is followed by the optional message body. CLRF divides the message header from the message body. CLRF line is mandatory even in cases when there is no message body in the SIP message.
generic-message = start-line *message-headers CRLF [message-body] start-line = Request-Line / Status-Line
It can be obviously decided if the message is a request or a response on the basis of its start-line. The start-line is either a request-line or a status-line.
The structure of request-line
Request-Line = Method SP Request-URI SP SIP-Version CRLF
- where SP is a single space character, CLRF is carriage-return line-feed
- where Method defines the method to be executed. A simple call can be handled with the following methods: REGISTER, INVITE, ACK, BYE and CANCEL
- where Request-URL is a SIP address
- where SIP-version is the version number of the used SIP
The structure of status line
Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
- where Status-Code is a 3 digit „integer” number that identifies in which of
the six response groups the given response message belongs (informative responses,
successful connection responses, redirect, unsuccessful request, server errors, generic errors)
- where Reason Pharse is the text name that is related to status code
Message header
SIP protocol defines several message-header types. The information content of these
message-header types and the syntax of providing this information mainly depend on
the message-header type itself. Moreover the semantic interpretation of the same header-fields
may also differ from the role the SIP message has in its environment. Considering the length of
this article I will not deal more with the detailed syntax and semantics analysis regarding the
header field types. I will only mention the ones that are needed to ring a telephone (via, to,
from, call-id, CSeq, Contact, Content-Length).
The general form requirements of SIP header fields:
field-name: field-value
The requirements regarding the syntax and semantics of field-value can strongly differ according to the header type. For more detailed information please have a look at the reference of SIP RFC3264.
Registration, authentication
Registration can take place in the communication process between
an UA and a server. The registration process can also accompany with an authentication
process if the server requires it. Besides registration some scenarios and events can
make authentication necessary for UAC such as initializing a call, terminating a
call via BYE SIP message or modification of a session.
SIP
authentication is based on HTTP authentication and uses the „DIGEST” mechanism:
the registration of UA to a SIP PBX is made by sending a registration request
to the server. The server returns the authentication information needed for
registration to the UA that wants to register.
This time the UA restructures the same registration message and completes it with
an authentication header. The authentication header is created from the information
received from the server. Now let's see it with a concrete example!
So the UA sends a REGISTER SIP message to the SIP server, in this case, as a result
of a registration request (it could be a call initialization because authentication
is also required in that case).
string message = "REGISTER sip:192.168.91.212:5060 SIP/2.0\r\n"
+ "Via:SIP/2.0/UDP "+mylocalIp+":5701;branch=z9hG4bK5b5077e0-e26f-4a50-bf16-10b5b22b591c;rport\r\n"
+ "To: " + myUserName + "<sip:" + myUserName + "@" + SIPproviderIP + ":5060>\r\n"
+ "From: " + myUserName + "<sip:" + myUserName + "@" + SIPproviderIP + ":5060>;tag=hetfgeeb\r\n"
+ "Call-ID: gdhisemewofqcjxysiwjjnrtfdwsfcmykvspmdxfnpllcrdsyi\r\n"
+ "CSeq: 1 REGISTER\r\n"
+ "Contact: <sip:" + myUserName + "@" + mylocalIp + ":5780>\r\n"
+ "Expires: 3600\r\n"
+ "Supported: 100rel\r\n"
+ "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE\r\n"
+ "Max-Forwards: 70\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n";
The structure of a Register message
The formal requirements of SIP messages, that were mentioned above, can be identified here. The following line compiles the request line of the message and it clearly shows that it is a SIP request.
"REGISTER sip:192.168.91.212:5060 SIP/2.0\r\n"
The following line marks the SIP server address (SIP uri) to which I would like to register. It is followed by the version number SIP/2.0\r\n" of the used SIP that is followed by the Carriage Return characters and they also close the start-line of the SIP message.
sip:192.168.91.212:5060
Via header
"Via:SIP/2.0/UDP "+mylocalIp+":5701;branch=z9hG4bK5b5077e0-e26f-4a50-bf16-10b5b22b591c;rport\r\n"
This line is already a header field that is mandatory to create a request. It marks the used SIP version of which value needs to be constant SIP/2.0 according to the current SIP standard. It also marks the data transfer protocol and the address where the addressee device needs to send its response to. Furthermore, a ; divided branch parameter that identifies the transaction created by the request definitely. The transaction has not been mentioned yet, it is not really important for our example but it is worth mentioning a few words about it.
SIP transactions
The SIP protocol organizes its messages into collections that includes a request and all the responses related to this request. These collections are called SIP transactions. Transactions are created with requests and they are ended with one or more final responses depending on the given request and its environment. More details about the semantics can be found in RFC3261 reference. So all requests create a transaction with the identifier of the VIA header branch parameter. With the help of it, the participants of the communication can definitely identify that the incoming SIP messages which of the transactions are related to. The branch parameter is built up by two parts. One part is "z9hG4bK" that is a constant value according to the standard. The other part of the branch parameter is a string that has been generated by a random generator.
To header
To: " + myUserName + "<sip:" + myUserName + "@" + SIPproviderIP + ":5060>\r\n"
It includes the recipient of the request message and its first optional parameter is the
display name of the caller. It is the myUserName in this example. This is followed by
the SIP URI of the recipient that can be followed by the TAG parameter. TAG is another
definition to identify dialogues; it is a string that is created randomly.
Dialogue
The connection evolved between two or more SIP devices during the call is called dialogue.
Usually dialogues are created with an INVITE message and destroyed with the BYE message.
The call-id is the TAG parameter of „to” header and „from” header and it identifies a dialogue.
From header
"From: " + myUserName + "<sip:" + myUserName + "@" + SIPproviderIP + ":5060>;tag=hetfgeeb\r\n"
This message header includes the optional display name that creates a request as well as its
SIP uri. Also it contains the randomly generated string TAG which identifies the current dialogue.
Call-ID header
"Call-ID: gdhisemewofqcjxysiwjjnrtfdwsfcmykvspmdxfnpllcrdsyi\r\n"
It is a generated unique identifier and its value is the same within a dialogue in every
request and response message. It is meant to identify the dialogues that are separated from each other.
CSeq header
"CSeq: 1 REGISTER\r\n"
This is the header that identifies the transactions between SIP devices through an unsigned 32 bit integer
number. This number is ascending by +1 in the consecutive transactions. Also the header
includes the method that creates the transaction in this case it is the REGISTER.
Contact header
"Contact: <sip:" + calleeUserName + "@" + calleeIPAddress + ">\r\n"
The contact header includes the UA SIP address that creates the request. Via this
header the UAs participating in the communication can contact with the
given UA.
Expires header
"Expires: 3600\r\n"
It specifies that the given UA registration should be active in what time period; it
is expressed in seconds. When this time is up, a new registration is needed
for the UA to receive calls.
Supported header
"Supported: 100rel\r\n"
It marks the optional SIP extensions of the UAC for the server.
Allow header
"Allow: INVITE, ACK, CANCEL, OPTIONS, BYE\r\n"
It includes the list of methods that can be processed by the given UA.
MAX forwards header
"Max-Forwards: 70\r\n"
All request messages include this header. It defines with the help of an integer number
that how many hops are needed to the given message to reach its destination. The standard
suggest 70 value to identify this value.
Content-Length
"Content-Length: 0\r\n"
The content-length header includes the length of the SIP message body and it is in bytes. In this sample code this length is 0 because the aim of the sample is only to ring a telephone.
Responses given to registration messages
To this SIP message the SIP server will respond with a 401 Unauthorized response message in case the UAS is a registrar or a redirect server. If the server is a proxy server then a 407 Proxy Authentication Required message is returned that includes the information which is required for the authentication in the WWW-Authenticate header:
SIP/2.0 401 Unauthorized Via: SIP/2.0/UDP 192.168.91.42:5701;branch=z9hG4bK5b5077e0-e26f-4a50-bf16-10b5b22b591c;received=192.168.91.42;rport=56498 From: oz871<sip:oz871@192.168.91.212:5060>;tag=hetfgeeb To: oz871<sip:oz871@192.168.91.212:5060>;tag=as2fa69ea8 Call-ID: gdhisemewofqcjxysiwjjnrtfdwsfcmykvspmdxfnpllcrdsyi CSeq: 1 REGISTER Server: Asterisk PBX 1.6.2.9-2ubuntu2 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO Supported: replaces, timer WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="64b5309c" Content-Length: 0
WWW-Authenticate header
Digest: It marks the name of the authentication system.
algorithm: It marks the algorithm that is used to calculate checksum. By default it is MD5.
realm: Associated protection domain.
nonce: A unique string that is defined by the server.
Registration completed with authentication header field
To finish registration successfully you need to resend your request by completing it
with the Authorization header.
Authorization: Digest username=oz871, realm="asterisk", nonce="64b5309c", response="7d612fdbb2b83b21cd6727faf4fcd014", uri="sip:192.168.91.212:5060", algorithm=MD5
Where Digest is the name of the authentication mechanism, the username is the defined name on the used realm, in this case it is „asterisk”. Nonce is the string that we previously received in the 401 or 407 response message, the response field is the key that is calculated on the basis of the signed MD5 algorithm. This is done with the utilization of username, realm, userpassword, sip method, sip uri and nonce. With it the server does the identification. In case the calculated value is correct you receive a 200 OK response message that informs you about the successful registration. In case the value is incorrect, 401 Unauthorized, 407 Proxy Authentication Required messages will be returned.
Transmission layer
SIP makes communication through UDP (User Datagram Protocol) protocol. It can be
realized easily with the help of
Microsoft .NET Framework. In this sample program I do the sending and receiving of
messages via the UdpClient object by using only a few lines:
UdpClient udpClient = new UdpClient();
udpClient.Connect(SIPproviderIP, 5060);
Byte[] sendBytes = Encoding.ASCII.GetBytes(sipMessage);
udpClient.Send(sendBytes, sendBytes.Length);
Byte[] receiveBytes = udpClient.Receive(ref remotendpoint);
string receivedMessage = Encoding.ASCII.GetString(receiveBytes);
| Ozeki
C# SIP softphone client example can be obtained by clicking the download link below: Download Ozeki C# SIP softphone client example! |
If you have any further questions do not hesitate to contact us! Send an Email to info@voip-sip-sdk.com
INTERMEDIATE
VoIP technology walkthrough
Softphone development
Webphone development
Mobile development
Voice recording
GETTING AROUND
Sitemap
Search the manual
API documentation
FAQ
Appendix

