commit
2dab6612c8
11
README.rst
11
README.rst
|
@ -89,6 +89,17 @@ directly on the host where Asterisk is running. Since Asterisk doesn't
|
|||
run on windows platforms (and probably never will) the agi part of the
|
||||
package can only be run on Asterisk platforms.
|
||||
|
||||
FastAGI
|
||||
-------
|
||||
|
||||
FastAGI support is a python based raw SocketServer, To start the server
|
||||
python fastagi.py should start it listening on localhost and the default
|
||||
asterisk FastAGI port. This does require the newest version of pyst2.
|
||||
The FastAGI server runs in as a Forked operation for each request, in
|
||||
an attempt to prevent blocking by a single bad service. As a result the
|
||||
FastAGI server may consume more memory then a single process. If you need
|
||||
to use a single process simply uncomment the appropriate line. Future versions
|
||||
of this will use a config file to set options.
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
|
|
@ -8,9 +8,9 @@ pyvr
|
|||
{'agi_callerid' : 'mars.putland.int',
|
||||
'agi_channel' : 'IAX[kputland@kputland]/119',
|
||||
'agi_context' : 'default',
|
||||
'agi_dnid' : '666',
|
||||
'agi_dnid' : '1000',
|
||||
'agi_enhanced' : '0.0',
|
||||
'agi_extension': '666',
|
||||
'agi_extension': '1000',
|
||||
'agi_language' : 'en',
|
||||
'agi_priority' : '1',
|
||||
'agi_rdnis' : '',
|
||||
|
@ -77,7 +77,7 @@ class AGIUsageError(AGIError):
|
|||
class AGIInvalidCommand(AGIError):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class AGI:
|
||||
"""
|
||||
This class encapsulates communication between Asterisk an a python script.
|
||||
|
@ -85,21 +85,24 @@ class AGI:
|
|||
Asterisk.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr):
|
||||
self._got_sighup = False
|
||||
signal.signal(signal.SIGHUP, self._handle_sighup) # handle SIGHUP
|
||||
sys.stderr.write('ARGS: ')
|
||||
sys.stderr.write(str(sys.argv))
|
||||
sys.stderr.write('\n')
|
||||
self.stderr.write('ARGS: ')
|
||||
self.stderr.write(str(sys.argv))
|
||||
self.stderr.write('\n')
|
||||
self.stdin = stdin
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
self.env = {}
|
||||
self._get_agi_env()
|
||||
|
||||
def _get_agi_env(self):
|
||||
while 1:
|
||||
line = sys.stdin.readline().strip()
|
||||
sys.stderr.write('ENV LINE: ')
|
||||
sys.stderr.write(line)
|
||||
sys.stderr.write('\n')
|
||||
line = self.stdin.readline().strip()
|
||||
self.stderr.write('ENV LINE: ')
|
||||
self.stderr.write(line)
|
||||
self.stderr.write('\n')
|
||||
if line == '':
|
||||
#blank line signals end
|
||||
break
|
||||
|
@ -108,9 +111,9 @@ class AGI:
|
|||
data = data.strip()
|
||||
if key != '':
|
||||
self.env[key] = data
|
||||
sys.stderr.write('class AGI: self.env = ')
|
||||
sys.stderr.write(pprint.pformat(self.env))
|
||||
sys.stderr.write('\n')
|
||||
self.stderr.write('class AGI: self.env = ')
|
||||
self.stderr.write(pprint.pformat(self.env))
|
||||
self.stderr.write('\n')
|
||||
|
||||
def _quote(self, string):
|
||||
""" provides double quotes to string, converts int/bool to string """
|
||||
|
@ -149,16 +152,16 @@ class AGI:
|
|||
command = command.strip()
|
||||
if command[-1] != '\n':
|
||||
command += '\n'
|
||||
sys.stderr.write(' COMMAND: %s' % command)
|
||||
sys.stdout.write(command)
|
||||
sys.stdout.flush()
|
||||
self.stderr.write(' COMMAND: %s' % command)
|
||||
self.stdout.write(command)
|
||||
self.stdout.flush()
|
||||
|
||||
def get_result(self, stdin=sys.stdin):
|
||||
"""Read the result of a command from Asterisk"""
|
||||
code = 0
|
||||
result = {'result': ('', '')}
|
||||
line = stdin.readline().strip()
|
||||
sys.stderr.write(' RESULT_LINE: %s\n' % line)
|
||||
line = self.stdin.readline().strip()
|
||||
self.stderr.write(' RESULT_LINE: %s\n' % line)
|
||||
m = re_code.search(line)
|
||||
if m:
|
||||
code, response = m.groups()
|
||||
|
@ -175,16 +178,16 @@ class AGI:
|
|||
if key == 'result' and value == '-1':
|
||||
raise AGIAppError("Error executing application, or hangup")
|
||||
|
||||
sys.stderr.write(' RESULT_DICT: %s\n' % pprint.pformat(result))
|
||||
self.stderr.write(' RESULT_DICT: %s\n' % pprint.pformat(result))
|
||||
return result
|
||||
elif code == 510:
|
||||
raise AGIInvalidCommand(response)
|
||||
elif code == 520:
|
||||
usage = [line]
|
||||
line = stdin.readline().strip()
|
||||
line = self.stdin.readline().strip()
|
||||
while line[:3] != '520':
|
||||
usage.append(line)
|
||||
line = stdin.readline().strip()
|
||||
line = self.stdin.readline().strip()
|
||||
usage.append(line)
|
||||
usage = '%s\n' % '\n'.join(usage)
|
||||
raise AGIUsageError(usage)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python
|
||||
# FastAGI service for Asterisk
|
||||
# Requires modified pyst2 to support reading stdin/out/err
|
||||
#
|
||||
# Copyright 2011 VOICE1, LLC
|
||||
# By: Ben Davis <ben@voice1-dot-me>
|
||||
|
||||
import sys
|
||||
import SocketServer
|
||||
import asterisk.agi
|
||||
# import pkg_resources
|
||||
# PYST_VERSION = pkg_resources.get_distribution("pyst2").version
|
||||
|
||||
__verison__ = 0.1
|
||||
|
||||
#TODO: Read options from config file.
|
||||
HOST, PORT = "127.0.0.1", 4573
|
||||
|
||||
class FastAGI(SocketServer.StreamRequestHandler):
|
||||
# Close connections not finished in 5seconds.
|
||||
timeout = 5
|
||||
def handle(self):
|
||||
try:
|
||||
agi=asterisk.agi.AGI(stdin=self.rfile, stdout=self.wfile, stderr=sys.stderr)
|
||||
agi.verbose("pyst2: FastAGI on: {}:{}".format(HOST, PORT))
|
||||
except TypeError as e:
|
||||
sys.stderr.write('Unable to connect to agi://{} {}\n'.format(self.client_address[0], str(e)))
|
||||
except SocketServer.socket.timeout as e:
|
||||
sys.stderr.write('Timeout receiving data from {}\n'.format(self.client_address))
|
||||
except SocketServer.socket.error as e:
|
||||
sys.stderr.write('Could not open the socket. Is someting else listening on this port?\n')
|
||||
except Exception as e:
|
||||
sys.stderr.write('An unknown error: {}\n'.format(str(e)))
|
||||
|
||||
if __name__ == "__main__":
|
||||
# server = SocketServer.TCPServer((HOST, PORT), FastAGI)
|
||||
server = SocketServer.ForkingTCPServer((HOST, PORT), FastAGI)
|
||||
|
||||
# Keep server running until CTRL-C is pressed.
|
||||
server.serve_forever()
|
Loading…
Reference in New Issue