download Download: sip-sms-example.zip

This article demonstrates how to use C# SIP softphone source of Ozeki VoIP SDK for creating a SIP SMS example.

What are SIP and SMS messages? When to use them?

In case of softphones important information is being transmitted in SIP messages. Often these messages are not only necessary for establishing phone calls, but complementary actions can also be made with them. For instance you can find out from a SIP message that the server you want to connect is currently not available. In this case the server probably requires maintenance or configuration. In everyday life it is critical for the maintainer to receive such an important message as soon as possible. To receive critical messages immediately, automated SMS sending is highly recommended.

Short Message Service (SMS) is a text messaging service component of phone, Web, or mobile communication systems. It uses standardized communications protocols to allow fixed line or mobile phone devices to exchange short text messages.

The main goal of this sample program is to demonstrate the efficient solution for this problem with the help of Ozeki VoIP SIP SDK.

This sample program is for presenting the significant and easy to use services that Ozeki VoIP SIP SDK offers. With this program you have the opportunity to make and receive calls. It is also for sending and receiving DTMF signals that are for navigating in IVR systems.

From SIP messages various and very important notifications can be received. These messages hold significant information that can be useful for different purposes.

For instance the maintainer of a system can receive an SMS automatically if something is wrong with the server. Maybe he is busy doing his other tasks and he does not have enough time to handle everything. This way he can act immediately and avert the problem as soon as possible.

People have their cell phones in arms reach therefore when they receive an SMS they will surely read it. That is why SMS messaging is so impressive and effective if it comes to notifications and alerts.

Automated SMS messages can be assigned to several notifications for example when you have an unanswered call. With this simple functionality you highly improve your system.

How to develop SIP SMS example?

You can find here how to configure the C# SIP softphone source of Ozeki VoIP SDK for creating a SIP SMS example

What configuration steps should be made?

  1. Download and extract the sample program.
  2. Load the sample program into Visual Studio.
  3. For the proper operation of the program a minimal configuration is required:
    In the telephone initialization section of the PhoneMain.cs file you need to replace the local IP address of the PC on which the system runs instead of "your local IP Address". Below you can find this step in details. This is the telephone initialization section of the PhoneMain.cs file:
    		private void InitializeSoftPhone()  
    		{  
    		    softPhone = SoftPhoneFactory.CreateSoftPhone("your local IP Address", 5700, 5750);  
    		    softPhone.IncomingCall += softPhone_IncomingCall;
    		    phoneLine = softPhone.CreatePhoneLine(new SIPAccount(true, "oz891", "oz891", "oz891", "oz891", "192.168.91.212", 5060));
    		    phoneLine.PhoneLineInformation += phoneLine_PhoneLineInformation;
    		  
    		    softPhone.RegisterPhoneLine(phoneLine);  
    		} 
    		
    In this section search for the following line:
    		softPhone = SoftPhoneFactory.CreateSoftPhone("your local IP Address", 5700, 5750);
    		
    In this line replace the local IP address of the PC on which the system runs instead of "your local IP Address".

    Then you need to provide the user data of your selected SIP PBX as the SIP account object values similarly to the following line:
    		phoneLine = softPhone.CreatePhoneLine(new SIPAccount(true, "oz891", "oz891", "oz891", "oz891", "192.168.91.212", 5060));
    		
  4. When you are finished you only need to build and run the program.

Graphical User Interface (GUI)

The sample program has been made by the Microsoft Windows Forms Presentation technology that is well known for Microsoft .Net developers. The basic aspect of the created interface was to demonstrate the services that Ozeki VoIP SIP SDK offers so it omits the visual elements. It has all the functions that a softphone needs like call initiation, receiving calls, sending and receiving DTMF signals, event display on the display screen.

For being demonstrative, the interface of the sample program includes a section for SMS sending (Figure 1). This section would probably be hidden in a real environment but for sake of representativeness it has been visualized in this sample program.

Now let's see the interface. In IPAddress field the IP address of the SMS server needs to be entered with which you wish to send SMS messages. Below this edit box, the User name and Password can be specified that are related to the SMS server. In SIP text field you can specify the SIP message part that will trigger the SMS sending. In Recipient filed you can enter the telephone number of the recipient. In SMS text field you can compose the body of the SMS message.

sms sending interface
Figure 1 - SMS sending interface

Running the program

After running the program the telephone automatically registers to the given SIP PBX with the given SIP account. If the registration process is ended successfully you can see Registration succeeded on the display. From this point the softphone is ready to establish and receive calls, to send and receive DTMF signals during calls for navigating in IVR systems. (The source code of the sample program includes settings that depend on the environment so after the download do not forget to customize it. After ending the call a notification is also received about the mentioned keywords.

SIP SMS example in C#

PhoneMain.cs code-behind file belonging to the program interface describes the control events related to the interface and connects the GUI with the logics. The sample program focuses on simplicity and representativeness. The PhoneMain.cs file includes the full logic of the sample program. By opening this PhoneMain.cs file, you can see a few lines of declaration right the beginning that are needed for the use of Ozeki VoIP SIP SDK.

public partial class PhoneMain : Form  
{  
    ISoftPhone softPhone;  
    IPhoneLine phoneLine;  
    PhoneLineState phoneLineInformation;  
    IPhoneCall call;  
    bool inComingCall;  
    SIPMessageLogger sipMessageLogger;  
...  

ISoftPhone: it represents a telephone, and its telephone line is represented by an IPhoneLine object. It is also possible to develop a multiline phone.

IPhoneLine: it represents a telephone line that you can register to a SIP PBX, for example, Asterisk, 3CX, or to other PBXs that are offered by free SIP providers. Registration is made via a SIP account.

PhoneLineState: it is an enum type that represents the telephone line status related to the PBX. For example registered, not registered, successful/unsuccessful registration.

IphoneCall: it represents a call: the status of the call, the direction of the call, on which telephone line it was created, who is the called person etc.

Softphone initialization (after loading the GUI)

By subscribing to the 'Loaded' event of the Windows Form windows, it is possible to start the initialization and registration of Ozeki SDK softphone right after 'PhoneMain' window is loaded.

private void InitializeSoftPhone()  
{  
    try  
    {  
        softPhone = SoftPhoneFactory.CreateSoftPhone(SoftPhoneFactory.GetLocalIP(), 5700, 5750);  
        softPhone.IncomingCall += softPhone_IncomingCall;  
        SIPAccount sipAccount = new SIPAccount(true, "o875", "oz875", "oz875", "oz875", "192.168.112.100", 5060);  
    	phoneLine = softPhone.CreatePhoneLine(sipAccount);  
        phoneLine.RegistrationStateChanged += phoneLine_PhoneLineInformation;  

        softPhone.RegisterPhoneLine(phoneLine);  

	    sipMessageLogger = new SIPMessageLogger();  
	    sipMessageLogger.SIPMessageReceived += (sipMessageLogger_SIPMessageReceived);  
	    Logger.Attach(sipMessageLogger);  
	    Logger.Open(LogLevel.Information);  
    }  
    catch(Exception ex)  
    {  
	    var sb = new StringBuilder();  
	    sb.AppendLine("Some error happened.");  
	    sb.AppendLine();  
	    sb.AppendLine("Exception:");  
	    sb.AppendLine(ex.Message);  
	    sb.AppendLine();  
	    
	    if(ex.InnerException != null)  
	    {  
	        sb.AppendLine("Inner Exception:");  
	        sb.AppendLine(ex.InnerException.Message);  
	        sb.AppendLine();  
	    }  
	    sb.AppendLine("StackTrace:");  
	    sb.AppendLine(ex.StackTrace);  

		MessageBox.Show(sb.ToString());  
    }
}  

Create an instance of the phone via the "softPhone" object and give the IP address of your computer and the port domain that can be used by the phone. Finally specify the port, at which the SIP messages arriving from the PBX are listened, as the last parameter.

Subscribe to the event that handles incoming calls of the telephone ("softPhone.IncomingCall") that occurs when there is an incoming call from the remote end.

Create a phoneLine with a SIP account that can be the user account of your corporate SIP PBX or a free SIP provider account. To display the status of the created telephone line, sign up to its "phoneLine.PhoneLineInformation" event.

When these things are done you only need to register the created "phoneLine" to the "softPhone". In this example only one telephone line is registered but of course multiple telephone line registration is also available.

After these steps you only need to deal with the handling of the calls and to display them onto the GUI.

Handling the calls

Ozeki SDK represents the incoming and outgoing calls through the IpPhoneCall interface. This interface includes the status of the given call, on which line it was created and who the called person is. On this object you can pick up or hang up calls. Let's see the event of the sample program.

  • Handling outgoing calls: for establishing an outgoing call, enter the number you wish to dial. Then press the 'Pick Up' button and the call starts. The surface buttons are assigned to triggers so let's look at the "Pick Up" button for details:
    		private void buttonPickUp_Click(object sender, EventArgs e)  
    		{  
    		    if (inComingCall)  
    		    {  
    		        inComingCall = false;  
    		        call.Answer();  
    		        return;  
    		    }  
    		  
    		    if (call != null)  
    		        return;  
    		  
    		    if (string.IsNullOrEmpty(labelDialingNumber.Text))  
    		        return;  
    		  
    		    if (phoneLineInformation != RegState.RegistrationSucceeded && phoneLineInformation != RegState.NoRegNeeded)  
    		    {  
    		        MessageBox.Show("Phone line state is not valid!");  
    		        return;  
    		    }  
    		  
    		    call = softPhone.CreateCallObject(phoneLine, labelDialingNumber.Text);  
    		    call.CallStateChanged += call_CallStateChanged;
    		    call.Start();  
    		}  
    		
    Since you can make and pick up the call with the very same button first you need to decide if it is an incoming or an outgoing call with the help of a simple bool variable truth verification (Incoming calls will be detailed later).

    Before initiating a phone call, check if the phoneline has successfully registered to the server when registration is required. If an inappropriate result is returned the user is informed about the reason of the failure.

    If the phoneline is registered, create an IPhoneCall object representing a call via the "softPhone.Call" method and its parameters. The first parameter is the telephone line on which you would like to initiate calls, the second parameter is the phone number to be called. In order to make your calls successful, wire up to some Call Events. Therefore, the audio data arriving from the remote end, the DTMF signal or changes in call status can be processed effectively.

    To subscribe for these necessary events you only need to actually start a call. You can do it with the Start() method of the call object. In this example it is the "call.Start()" line.
  • Handling incoming calls: Ozeki VoIP SIP SDK publishes the incoming calls through the "ISoftphone" InComingCall event.
    		private void softPhone_IncomingCall(object sender, VoIPEventArgs<IPhoneCall> e)  
    		{  
    		    InvokeGUIThread(() =>  
    		        {  
    		                labelCallStateInfo.Text = "Incoming call";  
    		                labelDialingNumber.Text = String.Format("from {0}", e.Item.DialInfo);  
    		                call = e.Item;  
    		                call.CallStateChanged += call_CallStateChanged;
    		                inComingCall = true;  
    		        });  
    		}
    		
    The code sample above is for handling this. It displays incoming calls on the display and registers onto the necessary events of the object representing incoming calls which was mentioned above. The incoming call variable notifies the Pick Up button if the call is an outgoing or an incoming one.
  • Ending calls: there are three different ways for ending a call that is in progress:
    • the user (this softphone) ends the call
    • the remote party ends the call
    • there is a break in network connection (error occurs and ends the call)
    You can take care of ending the call by pressing the Hang Up button. Just like the "Pick Up" button the "Hang Up" button is also connected to the event manager.

    If you press the "Hang Up" button the following event manager is responsible for ending the call:
    		private void buttonHangUp_Click(object sender, EventArgs e)  
    		{  
    		if (call != null)  
    		{  
    		    inComingCall = false;  
    		    call.HangUp();  
    		    call = null;  
    		}  
    		labelDialingNumber.Text = string.Empty;  
    		} 
    		
    Now it needs to be checked if there is an active call. If there is an active call you need to end it and delete the information related to dialing.
  • Displaying call status: Ozeki VoIP SIP SDK provides the following information about the call status: ringing, InCall, Completed, Rejected, etc. These call statuses are displayed via the CallStateChange event of "call" object. In this sample program I only focused on the essential options for being simple but demonstrative. Based on these essential option you can easily create further options.
    		private void call_CallStateChanged(object sender, CallStateChangedArgs e)  
    		{  
    		    InvokeGUIThread(() => { labelCallStateInfo.Text = e.State.ToString(); });  
    		  
    		    switch (e.State)  
    		    {  
    		        case CallState.Completed:  
    		            call.CallStateChanged -= call_CallStateChanged;
    		            call = null;  
    		            InvokeGUIThread(() => { labelDialingNumber.Text = string.Empty; });  
    		            break;  
    		        case CallState.Cancelled:  
    		            call.CallStateChanged -= call_CallStateChanged;
    		            call = null;  
    		            break;  
    		    }  
    		}  
    		
    The code above is only for reacting to the changes in the call status. For example: If the phone is picked up it starts the voice recording so you can send our audio data to the other party. Moreover it initializes the devices that are necessary for playing incoming audio data.
  • Handling incoming audio data: since we wired up to the MediaDataReceived event of the "call" in case of both outgoing and incoming calls, the incoming PCM audio data only needs to be forwarded to the sound system as it is demonstrated below.
  • Handling outgoing audio data: the PCM audio data originating from the microphone is forwarded to the "call" object that represents the actual call via the process of SendMediaData. Then audio data is compressed by Ozeki SIP SDK with the right audio codecs and then sent to the intended person according to the built communication channel. Beside, audio data is also stored for later keyword analysis.
  • Outgoing DTMF signals: DTMF signals can be sent after the call is established for - for example - navigating in the IVR menu system of the called call center. Ozeki VoIP SIP SDK allows to send DTMF signals in a simple way: the "StartDTMFSignal" method is called in the object representing the given call in the following way:
    		private void buttonKeyPadButton_MouseDown(object sender, MouseEventArgs e)  
    		{  
    		    if (call != null && call.CallState == CallState.InCall)  
    		    {  
    		        var btn = sender as Button;  
    		        if (btn != null)  
    		        {  
    		            int id;  
    		  
    		            if (btn.Tag != null && int.TryParse(btn.Tag.ToString(), out id))  
    		            {  
    		                call.StartDTMFSignal((DtmfNamedEvents)id);  
    		            }  
    		        }  
    		    }  
    		}  
    		
    According to RFC2833 the sending of the DTMF signal can represent how long the DTMF signal is being sent. In the sample program I would like to demonstrate this with the events of MouseDown and MouseUP buttons. By using MouseDown, the DTMF signal of the pressed button starts to be sent. By using MouseUP, the sending of the given DTMF signal is ended. The way of ending DTMF signal is similar to the way of start. On the object that represents the current call, the 'StopDTMFSignal' method is called in the following way (where the ID is the number-type DTMF signal according to the reference relating to the pressed button):
    		call.StopDTMFSignal((DtmfNamedEvents)id);
    		
  • Monitoring SIP messages: Ozeki VoIP SIP SDK transforms the content of SIP messages in a very simple way. For this purpose you only need to sign up to an event:
    		sipMessageLogger.SIPMessageReceived += (sipMessageLogger_SIPMessageReceived);
    		
    Now you need to check the content of messages:
    		void sipMessageLogger_SIPMessageReceived(object sender, GenericEventArgs<string> e)  
    		    {  
    		        if (e.Item.Contains(txb_SIPText.Text))  
    		        {  
    		            SendSMS();  
    		        }  
    		    }  
    		
    If there is a match for the searched SIP text section, an SMS will be sent. Sending of messages is done by an SMS gateway software. An HTTP request is sent to the HTTP API of the SMS gateway software. Finally, the SMS gateway sends out the SMS message to the recipient.

    For this purpose it is recommended to use a stable and reliable SMS gateway software. Such a stable SMS gateway is Ozeki NG SMS Gateway software. You can download it from http://www.ozekisms.com.
    		private void SendSMS()  
    		{  
    		    string url =  
    		    string.Format(@"http://{0}/api?action=sendmessage&username={1}&password={2}&recipient={3}&messagetype=SMS:TEXT&messagedata={4}",  
    		        Txb_IpAddress.Text, txb_UserName.Text,  
    		        Txb_Password.Text, Txb_recipient.Text,  
    		        Txb_SmsText.Text);  
    		
    		    WebRequest request = WebRequest.Create(url);  
    		
    		    request.GetResponse();  
    		}
    		

Related Pages

More information