Download: | call-hold.zip |
In this guide you will find all the information required to implement call holding function into your softphone using Ozeki VoIP SIP SDK. To use this example, you need to have Ozeki VoIP SIP SDK installed, and a reference to ozeki.dll should be added to your visual studio project. It's also recommended to visit the SIP INVITE and How to accept incoming call articles before you begin to study how to perform holding a call.
What does hold a call mean? When is it needed?
There are cases in remote communication when we need to wait for the callee for some reason. Holding a call means that the call was accepted but the caller has to wait for a call transfer or for some other action (Figure 1).
The most essential case of call holding is when you call a call center or a customer service where there is a limited number of agents at a time. In the case when all the agents are engaged, the caller needs to hold the call and wait for an agent to get free. In the most usual cases the call holding is indicated by the call center and the caller receives some music played during the waiting period.
How to put a call on Hold using C#?
Call holding does not differ so much from the original softphone concept. Ozeki VoIP SIP SDK provides the ToggleHold() method for a call that will do the trick for you. With this method you do not even need to check the state of the call, or store/check whether the call is on hold or not. This method does the work for you. If the call is on hold, the method will unhold it. In the case of unhold, the call will be put on hold.
The ToogleHold() method can set the call state to LocalHeld and RemoteHeld too. The LocalHeld state indicates that the call was held on the local computer, while the RemotHeld shows that the call was held by the remote party.
Call holding example in C#
using System; using System.Threading; using Ozeki.VoIP; namespace Call_hold { class Program { static ISoftPhone softphone; // softphone object static IPhoneLine phoneLine; // phoneline object static IPhoneCall call; private static void Main(string[] args) { // Create a softphone object with RTP port range 5000-10000 softphone = SoftPhoneFactory.CreateSoftPhone(5000, 10000); // SIP account registration data, (supplied by your VoIP service provider) var registrationRequired = true; var userName = "858"; var displayName = "858"; var authenticationId = "858"; var registerPassword = "858"; var domainHost = "192.168.115.100"; var domainPort = 5060; var account = new SIPAccount(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost, domainPort); // Send SIP regitration request RegisterAccount(account); // Prevents the termination of the application while (true) Thread.Sleep(50); } static void RegisterAccount(SIPAccount account) { try { phoneLine = softphone.CreatePhoneLine(account); phoneLine.RegistrationStateChanged += line_RegStateChanged; softphone.RegisterPhoneLine(phoneLine); } catch (Exception ex) { Console.WriteLine("Error during SIP registration: " + ex); } } static void line_RegStateChanged(object sender, RegistrationStateChangedArgs e) { if (e.State == RegState.NotRegistered || e.State == RegState.Error) Console.WriteLine("Registration failed!"); if (e.State == RegState.RegistrationSucceeded) { Console.WriteLine("Registration succeeded - Online!"); CreateCall(); } } static void CreateCall() { var numberToDial = "853"; call = softphone.CreateCallObject(phoneLine, numberToDial); call.CallStateChanged += call_CallStateChanged; call.Start(); } static void call_CallStateChanged(object sender, CallStateChangedArgs e) { Console.WriteLine("Call state: {0}.", e.State); if (e.State == CallState.InCall && e.State != CallState.LocalHeld) { Console.WriteLine("Press ENTER to put your call on hold."); Console.ReadLine(); call.Hold(); } if (e.State == CallState.LocalHeld) { Console.WriteLine("Press ENTER to take your call off hold."); Console.ReadLine(); call.Unhold(); } } } }
Communication through the network
After the call has been established between two parties, the call can be put on hold;
It can be done by sending SIP INVITE request, which sets the "Media Attribute" to
"sendonly" and "inactive" at the communicating parties.
The following steps are representing the holding function, after the call has been established
(so, the ACK message has been sent):
Step 1: The softphone puts the call on hold by sending an INVITE request to set the media attributes (UDP message, Softphone -> PBX)
INVITE sip:9999@192.168.112.215:5060 SIP/2.0 Via: SIP/2.0/UDP 192.168.112.215:6848;branch=z9hG4bKdad4b02d-105a-40f7-a6e2- 2f08327c787a;rport To: <sip:9999@192.168.112.215>;tag=dxrgsygo From: "1000"<sip:1000@192.168.112.215>;tag=llgsishn CSeq: 4 INVITE Call-ID: fvlwmncqufangggiqyakimoxupwqgjnujjbttehrraqckdvgrj Max-Forwards: 70 Contact: <sip:1000@192.168.112.215:6848> User-Agent: Ozeki VoIP SIP SDK v10.1.8 Content-Type: application/sdp Proxy-Authorization:Digest username="1000",realm="OzekiPBX", nonce="d5a4e0e18c60423fb5ce0d1b19c960dd", response="50aa459d404d4e0ef0d337e50b950218",uri="sip:9999@192.168.112.215:5060", algorithm=MD5 Content-Length: 589 v=0 o=- 1557342975 1557342976 IN IP4 192.168.112.215 s=Ozeki VoIP SIP SDK v10.1.8 c=IN IP4 192.168.112.215 t=0 0 m=audio 6677 RTP/AVP 8 a=rtpmap:8 PCMA/8000 a=sendonly m=video 7937 RTP/AVP 34 a=rtpmap:34 H263/90000 a=fmtp:34 QCIF=1;CIF=1 a=inactive
Step 2: The other party sends back the SIP 200 OK message via the PBX (UDP message, PBX -> Softphone)
SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.112.215:6848;branch=z9hG4bKdad4b02d-105a-40f7-a6e2- 2f08327c787a;rport=6848;received=192.168.112.215 From: "1000"<sip:1000@192.168.112.215>;tag=llgsishn Call-ID: fvlwmncqufangggiqyakimoxupwqgjnujjbttehrraqckdvgrj CSeq: 4 INVITE To: <sip:9999@192.168.112.215>;tag=dxrgsygo Contact: <sip:9999@192.168.112.215:5060> User-Agent: Ozeki Phone System XE v5.3.1 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REGISTER, SUBSCRIBE, NOTIFY, REFER, INFO, MESSAGE Content-Type: application/sdp Content-Length: 495 v=0 o=- 724034129 559580418 IN IP4 192.168.112.215 s=Ozeki Call c=IN IP4 192.168.112.215 t=0 0 m=audio 5673 RTP/AVP 8 a=rtpmap:8 PCMA/8000 a=recvonly m=video 8748 RTP/AVP 34 a=rtpmap:34 H263/90000 a=fmtp:34 QCIF=1;CIF=1 a=inactive
Step 3: ACK message is being sent back via the PBX (UDP message, Softphone -> PBX)
ACK sip:9999@192.168.112.215:5060 SIP/2.0 Via: SIP/2.0/UDP 192.168.112.215:6848;branch=z9hG4bKe951e75a-8da2-4c4f-9440- 3300f4166389;rport To: <sip:9999@192.168.112.215>;tag=dxrgsygo From: "1000"<sip:1000@192.168.112.215>;tag=llgsishn CSeq: 4 ACK Call-ID: fvlwmncqufangggiqyakimoxupwqgjnujjbttehrraqckdvgrj Max-Forwards: 70 Contact: <sip:1000@192.168.112.215:6848> User-Agent: Ozeki VoIP SIP SDK v10.1.8 Content-Length: 0
Related Pages
More information
- How to build a softphone voip sip client
- Register to SIP PBX
- Voip softphone development
- How to encrypt voip sip calls with sip encryption
- How to encrypt voip sip calls with rtp encryption
- How to ring a sip extension csharp example for sip invite
- How to make a sip voice call using csharp
- Voip multiple phone lines
- How to send stream of voice data into call using csharp microphone
- How to receive voice from SIP voice call using csharp speaker
- How to make conference voice call using voip sip
- How to play an mp3 file into a voice call using csharp
- How to convert text to speech and play that into a call using csharp
- How to use Microsoft Speech Platform 11 for TTS and STT
- How to record voip sip voice call
- How to accept incoming call using csharp
- How to reject incoming call using csharp
- How to read Headset buttons using Bluetooth
- How to implement auto answer using csharp
- How to recognize incoming voice using speech to text conversion
- Voip forward call
- Voip blind transfer
- Voip attended transfer
- Voip do not disturb
- Voip call hold
- SIP Message Waiting Indication
- Voip DTMF signaling
- How to work with sip and sdp in voip sip calls
- How to work with rtp in voip sip calls
- How to make voip video calls in csharp
- Voip video codec
- Shows how to use SpeechToText Google API
- How to convert Text to Speech using C# and Google
- Azure Text-to-Speech