def _protocol_send(self, command, args=''): """Access parent method _protocol_send """ self.log.debug("Execute: %s args='%s'" % (command, safe_str(args))) response = super(PlivoOutboundEventSocket, self)._protocol_send(command, args) self.log.debug("Response: %s" % str(response)) if self.has_hangup(): raise RESTHangup() return response
def wait_for_action(self, timeout=3600, raise_on_hangup=False): """ Wait until an action is over and return action event. """ self.log.debug("wait for action start") try: event = self._action_queue.get(timeout=timeout) self.log.debug("wait for action end %s" % str(event)) if raise_on_hangup is True and self.has_hangup(): self.log.warn("wait for action call hung up !") raise RESTHangup() return event except gevent.queue.Empty: if raise_on_hangup is True and self.has_hangup(): self.log.warn("wait for action call hung up !") raise RESTHangup() self.log.warn("wait for action end timed out!") return Event()
def _protocol_sendmsg(self, name, args=None, uuid='', lock=False, loops=1): """Access parent method _protocol_sendmsg """ self.log.debug("Execute: %s args=%s, uuid='%s', lock=%s, loops=%d" \ % (name, safe_str(args), uuid, str(lock), loops)) response = super(PlivoOutboundEventSocket, self)._protocol_sendmsg(name, args, uuid, lock, loops) self.log.debug("Response: %s" % str(response)) if self.has_hangup(): raise RESTHangup() return response
def process_call(self): """Method to proceed on the call This will fetch the XML, validate the response Parse the XML and Execute it """ params = {} for x in range(MAX_REDIRECT): try: # update call status if needed if self.has_hangup(): self.session_params['CallStatus'] = 'completed' # case answer url, add extra vars to http request : if x == 0: params = self.get_extra_fs_vars(event=self.get_channel()) # fetch remote restxml self.fetch_xml(params=params) # check hangup if self.has_hangup(): raise RESTHangup() if not self.xml_response: self.log.warn('No XML Response') if not self.has_hangup(): self.hangup() raise RESTHangup() # parse and execute restxml self.lex_xml() self.parse_xml() self.execute_xml() self.log.info('End of RESTXML') return except RESTRedirectException, redirect: # double check channel exists/hung up if self.has_hangup(): raise RESTHangup() res = self.api('uuid_exists %s' % self.get_channel_unique_id()) if res.get_response() != 'true': self.log.warn("Call doesn't exist !") raise RESTHangup() # Set target URL to Redirect URL # Set method to Redirect method # Set additional params to Redirect params self.target_url = redirect.get_url() fetch_method = redirect.get_method() params = redirect.get_params() if not fetch_method: fetch_method = 'POST' # Reset all the previous response and element self.xml_response = "" self.parsed_element = [] self.lexed_xml_response = [] self.log.info("Redirecting to %s %s to fetch RESTXML" \ % (fetch_method, self.target_url)) # If transfer is in progress, break redirect xfer_progress = self.get_var( 'plivo_transfer_progress') == 'true' if xfer_progress: self.log.warn('Transfer in progress, breaking redirect to %s %s' \ % (fetch_method, self.target_url)) return gevent.sleep(0.010) continue except RESTSIPTransferException, sip_redirect: self.session_params['SIPTransfer'] = 'true' self.session_params['SIPTransferURI'] = sip_redirect.get_sip_url() \ or '' self.log.info("End of RESTXML -- SIPTransfer done to %s" % sip_redirect.get_sip_url()) return
def _run(self): self.connect() self.resume() # Linger to get all remaining events before closing self.linger() self.myevents() self.divert_events('on') if self._is_eventjson: self.eventjson('CUSTOM conference::maintenance plivo::dial') else: self.eventplain('CUSTOM conference::maintenance plivo::dial') # Set plivo app flag self.set('plivo_app=true') # Don't hangup after bridge self.set('hangup_after_bridge=false') channel = self.get_channel() self.call_uuid = self.get_channel_unique_id() # Set CallerName to Session Params self.session_params['CallerName'] = channel.get_header( 'Caller-Caller-ID-Name') or '' # Set CallUUID to Session Params self.session_params['CallUUID'] = self.call_uuid # Set Direction to Session Params self.session_params['Direction'] = channel.get_header('Call-Direction') aleg_uuid = '' aleg_request_uuid = '' forwarded_from = get_substring( ':', '@', channel.get_header('variable_sip_h_Diversion')) # Case Outbound if self.session_params['Direction'] == 'outbound': # Set To / From called_no = channel.get_header("variable_plivo_to") if not called_no or called_no == '_undef_': called_no = channel.get_header('Caller-Destination-Number') called_no = called_no or '' from_no = channel.get_header("variable_plivo_from") if not from_no or from_no == '_undef_': from_no = channel.get_header('Caller-Caller-ID-Number') or '' # Set To to Session Params self.session_params['To'] = called_no.lstrip('+') # Set From to Session Params self.session_params['From'] = from_no.lstrip('+') # Look for variables in channel headers aleg_uuid = channel.get_header('Caller-Unique-ID') aleg_request_uuid = channel.get_header( 'variable_plivo_request_uuid') # Look for target url in order below : # get plivo_transfer_url from channel var # get plivo_answer_url from channel var xfer_url = channel.get_header('variable_plivo_transfer_url') answer_url = channel.get_header('variable_plivo_answer_url') if xfer_url: self.target_url = xfer_url self.log.info("Using TransferUrl %s" % self.target_url) elif answer_url: self.target_url = answer_url self.log.info("Using AnswerUrl %s" % self.target_url) else: self.log.error('Aborting -- No Call Url found !') if not self.has_hangup(): self.hangup() raise RESTHangup() return # Look for a sched_hangup_id sched_hangup_id = channel.get_header( 'variable_plivo_sched_hangup_id') # Don't post hangup in outbound direction # because it is handled by inboundsocket self.default_hangup_url = None self.hangup_url = None # Set CallStatus to Session Params self.session_params['CallStatus'] = 'in-progress' # Set answered flag to true in case outbound call self.answered = True accountsid = channel.get_header("variable_plivo_accountsid") if accountsid: self.session_params['AccountSID'] = accountsid # Case Inbound else: # Set To / From called_no = channel.get_header("variable_plivo_destination_number") if not called_no or called_no == '_undef_': called_no = channel.get_header('Caller-Destination-Number') called_no = called_no or '' from_no = channel.get_header('Caller-Caller-ID-Number') or '' # Set To to Session Params self.session_params['To'] = called_no.lstrip('+') # Set From to Session Params self.session_params['From'] = from_no.lstrip('+') # Look for target url in order below : # get plivo_transfer_url from channel var # get plivo_answer_url from channel var # get default answer_url from config xfer_url = self.get_var('plivo_transfer_url') answer_url = self.get_var('plivo_answer_url') if xfer_url: self.target_url = xfer_url self.log.info("Using TransferUrl %s" % self.target_url) elif answer_url: self.target_url = answer_url self.log.info("Using AnswerUrl %s" % self.target_url) elif self.default_answer_url: self.target_url = self.default_answer_url self.log.info("Using DefaultAnswerUrl %s" % self.target_url) else: self.log.error('Aborting -- No Call Url found !') if not self.has_hangup(): self.hangup() raise RESTHangup() return # Look for a sched_hangup_id sched_hangup_id = self.get_var('plivo_sched_hangup_id') # Set CallStatus to Session Params self.session_params['CallStatus'] = 'ringing' if not sched_hangup_id: sched_hangup_id = '' # Add more Session Params if present if aleg_uuid: self.session_params['ALegUUID'] = aleg_uuid if aleg_request_uuid: self.session_params['ALegRequestUUID'] = aleg_request_uuid if sched_hangup_id: self.session_params['ScheduledHangupId'] = sched_hangup_id if forwarded_from: self.session_params['ForwardedFrom'] = forwarded_from.lstrip('+') # Remove sched_hangup_id from channel vars if sched_hangup_id: self.unset('plivo_sched_hangup_id') # Run application self.log.info('Processing Call') try: self.process_call() except RESTHangup: self.log.warn('Channel has hung up, breaking Processing Call') except Exception, e: self.log.error('Processing Call Failure !') # If error occurs during xml parsing # log exception and break self.log.error(str(e)) [ self.log.error(line) for line in \ traceback.format_exc().splitlines() ]