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
Exemple #2
0
 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() ]