sys.Dial timeout, missed call notification

New features you'd like see on SIP Sorcery
Post Reply
MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

sys.Dial timeout, missed call notification

Post by MikeTelis » Sun Aug 30, 2009 7:08 am

I've noticed that "overall time-out" parameter I had been using on MSS doesn't work on Sipsorcery. Is there any other way?

I'm talking about:

sys.Dial("me@local",30)

where 30 means that the call must be terminated if not answered within 30 sec.

What I'm trying to do is to write a chunk of code informing me of missed calls. I think that having time-out parameter in sys.Dial won't be enough: sometimes the caller will hangup before I answer incoming call and SS will abort my script.

I checked out this construction:

Code: Select all

begin
  # call processing
rescue
  if sys.In
    #notify of missed call
  end
end
Of course, I should do more checking (besides sys.In) to determine if the call was aborted because the caller hang up. Is there any ready-made function, system variable or something like that?

Aaron
Site Admin
Posts: 4652
Joined: Thu Jul 12, 2007 12:13 am

Post by Aaron » Sun Aug 30, 2009 9:29 am

I've checked that function and it's working correctly on my test.

Regards,

Aaron

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Post by MikeTelis » Sun Aug 30, 2009 6:11 pm

Interesting... will double-check that (apparently I was fooled by the fact you removed this parameter from sys.Dial description in Sipsorcery dialplan help.

Anyway, even if it works, it won't solve the problem. Let me try to explain again. Suppose I received an incoming call and routed it to my ATA using sys.Dial command. I pick-up the phone, you terminate Ruby script, everybody's happy. Now, suppose the caller dropped call before I answered it -- you also terminate Ruby script, but this case is different for me as a user, because I actually missed incoming call (and I want to send a notification of this sad fact).

Thus, I need to distinguish between a case where sys.Dial completed normally (200 OK) and when you aborted it due to some other reason. Note putting some code after sys.Dial isn't a solution because you actually abort Ruby and the only way to intercept this situation is by "rescue" clause.

Hope my question is more or less clear now.

Sincerely,

Mike

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Post by MikeTelis » Sun Aug 30, 2009 6:52 pm

Update: I checked and indeed, time-out parameter is accepted and processed, control gets back to my Ruby script. I call the following procedure after sys.Dial:

Code: Select all

def status
  if (ptr = sys.LastDialled[0]).nil?
    @code = 487; @reason = 'Cancelled by Sipsorcery'
  else
    ptr = ptr.TransactionFinalResponse
    @code = ptr.StatusCode; @reason = ptr.ReasonPhrase
#   sys.Log("#{ptr.ToString()}")
  end
end
and it fails with the following error message:

undefined method `StatusCode' for nil:NilClass

I believe it's a bug in your code, please check.

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Post by MikeTelis » Thu Sep 03, 2009 2:43 pm

Yet another update: I found a solution. Here it is:

Code: Select all

# *****************************  S T A T U S  ******************************

def status
  begin
    if (ptr = sys.LastDialled[0]).nil?
      @code = 487; @reason = 'Cancelled by Sipsorcery'
    else
      ptr = ptr.TransactionFinalResponse
      @code = ptr.StatusCode; @reason = ptr.ReasonPhrase
#     sys.Log("#{ptr.ToString()}")
    end
  rescue
    @code = 480; @reason = 'No answer'
  end
end

# *******************************  M A I N  ********************************
begin
  if sys.In
  # ... processing incoming call ...
    name = req.Header.From.FromName.to_s     # create a copy of FromName
  else
  # ... processing outgoing call ...
  end
rescue
  if $!.to_s =~ /Thread was being aborted./
    status()	# check call status
    if sys.In && (@code > 200)
      sys.Email 'myemail@address.com',"Missed call from #{name}",<<-ENDOFMSG
Hi Mike,

you missed a call from:

Host: #{req.Header.from.FromURI.Host}
User: #{req.Header.from.FromURI.User}
Name: #{req.Header.From.FromName}

Rejected with code #{@code}, reason '#{@reason}'
ENDOFMSG
    end 	# sys.In
  else
    # Gives a lot more details at what went wrong (borrowed from Myatus' dialplan)
    sys.Log("** Error: " + $!)
  end
end
The code works but do I feel satisfied? Gosh, no! The above looks more like a patch rather than a neat, lean code. I still believe that sys.LastDialled[0].TransactionFinalResponse.StatusCode must be defined and set when we return from sys.Dial due to time-out. And it should be set to something when processing of incoming call by Ruby script is aborted because the caller dropped the call.

A wish? I suggest that we have a method (something like sys.WasConnected) returning true if sys.Dial completed with OK (code 200) and false otherwise.

A more radical and versatile solution would be in calling a dedicated script when a call (both incoming and outgoing) is terminated. It'd give us a lot of opportunities. The least we could do -- calculate duration of a call.

Post Reply