Return to LanScape's home page Go back a page...       Active TopicsActive Topics   Display List of Forum MembersMember List   Knowledge Base SearchSearch   HelpHelp  RegisterRegister  LoginLogin

LanScape VOIP Media Engine™ - Technical Support
 LanScape Support Forum -> LanScape VOIP Media Engine™ - Technical Support
Subject Topic: Determine Phone Line Available Post ReplyPost New Topic
Author
Message << Prev Topic | Next Topic >>
ajdiaz
Junior
Junior


Joined: December 10 2007
Location: United States
Posts: 76
Posted: January 30 2008 at 3:00pm | IP Logged Quote ajdiaz

I have an application that needs to place 20 outbound phone calls at once. I have 20 different threads being launched at once. How do I determine which phone line is available? I could query every single line for its status, but I was wondering if the MediaEngine handles line management for outbound calls? I do not want all 20 threads to try to make a call in line #0 because all of them querying at the same time will think line 0 is available.

Do you have any suggestions on how to do this so that each thread gets a different available line without clashing?
Back to Top View ajdiaz's Profile Search for other posts by ajdiaz
 
support
Administrator
Administrator


Joined: January 26 2005
Location: United States
Posts: 1666
Posted: January 30 2008 at 5:37pm | IP Logged Quote support

Hi Alex,

If your app has many threads and all the threads want to make outgoing calls using either the MakeCall() or MakeCallUri() API procs, the media engine will internally serialize the “make call” requests for each phone line such that no two app threads are able to use the same phone line for outgoing calls.

A very easy way for your threads to make outgoing calls would be to call the following C# procedure:

Code:

 //////////////////////////////////////////////////////////// /////////////
//
// This procedure can be called by a managed code thread to make an
// outbound call using any available phone line. If this proc detects
// that the phone line is already in use, it will try the next line.
// Input parameters:
//
//      MediaEngine - An instance of your voip media engine.
//
//      MaxPhoneLines - The max number of phone lines.
//
//      CallUri - The destination of the call.
//      Something like "sip:1234@domain.com:5060" or "sip:1234@1.2.3.4:5060"
//
// Return to the caller:
//
//      false - Error. call not placed.
//
//      true - Success. The call was placed.
//
 //////////////////////////////////////////////////////////// /////////////
public static bool BlindMakeCall(
    VoipMediaEngine MediaEngine, 
    int MaxPhoneLines,
    String CallUri,
    bool UseSipProxy
    )
{
    bool ret = false;
    int CurPhoneLine;
     VoipMediaEngine.TELEPHONY_RETURN_VAL UE status;
    VoipMediaEngine.LINE_STATE LineState;
    int LineBeingUsedCount = 0;


    LineState = new VoipMediaEngine.LINE_STATE();


    // try to make a phone call using any line.
    for (CurPhoneLine = 0; CurPhoneLine < MaxPhoneLines; CurPhoneLine++)
    {
        // get the current line status.
        status = MediaEngine.GetLineStatus(CurPhoneLine, LineState);

        if (status == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
        {
              // make sure the line is on hook.
              if (LineState.State == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipOnHook)
              {
                  // try to make a call using this line.
                  status = MediaEngine.MakeCallUri(
                      CallUri,
                      UseSipProxy,
                      CurPhoneLine,
                      false,          // asynchronous call.
                      0                 // call answer timeout Ms not used.
                      );


                  if (status ==  VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipCallAlreadyInProgr ess)
                  {
                      // the line is already being used.
                      LineBeingUsedCount++;
                  }
                  else if (status == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
                  {
                      // the call has been made and we are connected.
                      //

                      // let the call exist for 2 seconds.
                      Thread.Sleep(2000);

                      // terminate the call.
                      status = MediaEngine.TerminateCall(
                            CurPhoneLine,
                            true,           // synchronous call terminate.
                            2000              // call terminate timeout Ms.
                            );

                      if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
                      {
                          // handle the error.
                      }

                      // the call has been made. return to the
                      // caller.
                      ret = true;

                      break;
                  }
                  else
                  {
                      // some other error.
                  }
              }
              else
              {
                  // the line is already being used.
                  LineBeingUsedCount++;
              }
        }
    }

    return (ret);
}


The code above uses very little logic on the part of the VOIP app and is quick.

Another way would be for your VOIP app to serialize access to the phone lines so you know exactly what lines are being used for outgoing calls. That way your app can only try phone lines it knows is available.

A file named “BlindMakeCall.cs” has been placed into your support FTP account that contains the proc above.


Support

Back to Top View support's Profile Search for other posts by support Visit support's Homepage
 
support
Administrator
Administrator


Joined: January 26 2005
Location: United States
Posts: 1666
Posted: January 31 2008 at 12:14pm | IP Logged Quote support

Alex,

Here is a variation of the above proc that also handles both synchronous and asynch “make calls”.

Check your support FTP account for the “BlindMakeCallSynchronous.cs” module.

Thanks,

Support


Code:


//////////////////////////////////////////////////////////// /////////////
//
// This procedure can be called by a managed code thread to make an
// outbound call using any available phone line. If this proc detects
// that the phone line is already in use, it will try the next line.
// Input parameters:
//
//      MediaEngine - An instance of your voip media engine.
//
//      MaxPhoneLines - The max number of phone lines.
//
//      CallUri - The destination of the call. Something like
//      "sip:1234@domain.com:5 060" or "sip:1234@1.2.3.4:5060"
//
//      UseSipProxy - true if using a SIP proxy.
//
//      Synchronous - true if calling synchronously.
//
//      SynchronousTimeoutMs - The amount of time to wait for the call
//      to connect if using synchronous mode. if
//      not using synchronous mode, this parameter
//      is ignored.
//
// Return to the caller:
//
//      -1 - Error. call not placed.
//
//      0 to MaxPhoneLines-1 - Success. The call was placed. the return
//      value is the phone line used.
//
//////////////////////////////////////////////////////////// /////////////
public static int BlindMakeCall(
    VoipMediaEngine MediaEngine,
    int MaxPhoneLines,
    String CallUri,
    bool UseSipProxy,
    bool Synchronous,
    uint SynchronousTimeoutMs
    )
{
    int PhoneLineUsedForCall = -1;
    int CurPhoneLine;
    VoipMediaEngine.TELEPHONY_RETURN_VAL UE status;
    VoipMediaEngine.LINE_STATE LineState;
    int LineBeingUsedCount = 0;
    bool done;
    bool WriteToConsole = true;



     LineState = new VoipMediaEngine.LINE_STATE();


    // try to make a phone call using any line.
    for (CurPhoneLine = 0, done = false; !done && (CurPhoneLine < MaxPhoneLines); CurPhoneLine++)
    {
        // get the current line status.
        status = MediaEngine.GetLineStatus(CurPhoneLine, LineState);

        if (status == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
        {
             // make sure the line is on hook.
             //if (LineState.State == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipOnHook)
             if (true)
             {
                if (WriteToConsole)
                {
                     Console.WriteLine(
                          "Thread {0} attempting call on line {1}",
                          Thread.CurrentThread.ManagedThreadId,
                          CurPhoneLine
                          );
                }

                // try to make a call using this line.
                status = MediaEngine.MakeCallUri(
                     CallUri,
                     UseSipProxy,
                     CurPhoneLine,
                     Synchronous,
                     SynchronousTimeoutMs
                     );

                if (status == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipCallAlreadyInProgr ess)
                {
                      // the line is already being used.
                     LineBeingUsedCount++;

                      if (WriteToConsole)
                      {
                          Console.WriteLine(
                               "Thread {0} call failed. Line {1} already in use.",
                               Thread.CurrentThread.ManagedThreadId,
                               CurPhoneLine
                               );
                     }

                      // try another line.
                      //
                }
                else
                {
                      if (Synchronous)
                      {
                          if ((status == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess) ||
                               (status == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipFarEndError) ||
                               (status == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipFarEndIsBusy))
                          {
                               // The phone call initiated without error. if we received the
                               // SipInCall status, the call actuall connected. if we received
                               // the SipFarEndIsBusy status, the far end is busy and cannot
                               // accept the call. if we received the SipFarEndError status,
                               // the far end of the call returned some kind of error.
                               //
                               PhoneLineUsedForCall = CurPhoneLine;


                               if (WriteToConsole)
                               {
                                   Console.WriteLine(
                                       "SUCCESS - Thread {0} phone line {1} completed.",
                                       Thread.CurrentThread.ManagedThreadId,
                                       CurPhoneLine
                                       );
                               }

                               done = true;
                          }
                          else
                          {
                               // some other error.
                               if (WriteToConsole)
                               {
                                   // some other error.
                                   Console.WriteLine(
                                       "Thread {0} call failed. Trying another line.",
                                       Thread.CurrentThread.ManagedThreadId
                                       );

                                   // try another line.
                                   //
                               }
                          }
                     }
                     else
                      {
                          if (status == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
                          {
                               // the call has been made. wait for the "in call" state, a busy indication
                               // or a call a far end call error.
                               //
                               for (; !done; )
                               {
                                   // get the current line status.
                                   status = MediaEngine.GetLineStatus(CurPhoneLine, LineState);

                                   if (status != VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipSuccess)
                                   {
                                       // error reading line status
                                       done = true;

                                       if (WriteToConsole)
                                       {
                                            Console.WriteLine(
                                                "Thread {0} call failed. Error reading line status",
                                                Thread.CurrentThread.ManagedThreadId
                                                );
                                       }
                                   }
                                   else
                                   {
                                       if ((LineState.State == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipInCall) ||
                                            (LineState.State == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipFarEndError) ||
                                            (LineState.State == VoipMediaEngine.TELEPHONY_RETURN_VALUE.SipFarEndIsBusy))
                                       {
                                             // The phone call initiated without error. if we received the
                                             // SipInCall status, the call actuall connected. if we received
                                             // the SipFarEndIsBusy status, the far end is busy and cannot
                                             // accept the call. if we received the SipFarEndError status,
                                             // the far end of the call returned some kind of error.
                                             //
                                            PhoneLineUsedForCall = CurPhoneLine;


                                             if (WriteToConsole)
                                             {
                                                Console.WriteLine(
                                                     "SUCCESS - Thread {0} phone line {1} completed.",
                                                     Thread.CurrentThread.ManagedThreadId,
                                                     CurPhoneLine
                                                     );
                                            }

                                            done = true;
                                       }
                                       else
                                       {
                                             // wait a bit until we poll status again.
                                            Thread.Sleep(20);
                                       }
                                   }
                               }
                          }
                          else
                          {
                               if (WriteToConsole)
                               {
                                   // some other error.
                                   Console.WriteLine(
                                       "Thread {0} call failed. Trying another line.",
                                       Thread.CurrentThread.ManagedThreadId
                                       );
                               }

                               // try another line.
                               //
                          }
                     }
                }
             }
             else
             {
                // the line is already being used.
                LineBeingUsedCount++;

                if (WriteToConsole)
                {
                     Console.WriteLine(
                          "Thread {0} call failed. Line {1} already in use.",
                          Thread.CurrentThread.ManagedThreadId,
                          CurPhoneLine
                          );
                }

                // try another line.
                //
             }
        }
        else
        {
             if (WriteToConsole)
             {
                // some other error.
                Console.WriteLine(
                     "Thread {0} call failed. Trying another line.",
                     Thread.CurrentThread.ManagedThreadId
                     );

                // try another line.
                //
             }
        }
    }

    return (PhoneLineUsedForCall);
}


Back to Top View support's Profile Search for other posts by support Visit support's Homepage
 

If you wish to post a reply to this topic you must first login
If you are not already registered you must first register

  Post ReplyPost New Topic
Printable version Printable version

Forum Jump
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot delete your posts in this forum
You cannot edit your posts in this forum
You cannot create polls in this forum
You cannot vote in polls in this forum






Contact LanScape Hear what the Lawyers have to say How youm may use this site Read your privacy rights