python-ami
python-ami copied to clipboard
Incorrect pack deccoding on EventList.
Hello. Unfortunately, AMIClient dispatches responses and events incorrectly.
There are a few types of responses which is marked as EventList. These responses contain a several elements divided by '\r\n\r\n'. As soon, AMIClient wait for this separator to finish pack it cannot catch these types of response.
For example, Action: Status. This action might respond with list of active channels.
Action: Status
Response: Success EventList: start Message: Channel status will follow
Event: Status Privilege: Call Channel: SIP/3030-00000002 ChannelState: 6 ChannelStateDesc: Up CallerIDNum: 3030 CallerIDName: 3030 ConnectedLineNum:
ConnectedLineName: Accountcode: Context: exten-voicemail-sub Exten: s Priority: 5 Uniqueid: 1542489290.45 Type: SIP DNID: 2020 EffectiveConnectedLineNum: EffectiveConnectedLineName: TimeToHangup: 0 BridgeID: Linkedid: 1542489290.45 Application: VoiceMail Data: 3030@default,b Nativeformats: (ulaw) Readformat: ulaw Readtrans: Writeformat: ulaw Writetrans: Callgroup: 0 Pickupgroup: 0 Seconds: 285 Event: StatusComplete EventList: Complete ListItems: 1 Items: 1
But AMIClient passes only first element.
def fire_recv_pack(self, pack): print("Received pack: \n{}\n\n".format(pack)) if Response.match(pack): response = Response.read(pack) self.fire_recv_reponse(response) return if Event.match(pack): event = Event.read(pack) self.fire_recv_event(event) return self._fire_on_unknown(pack=pack)
Output is
Received pack: Response: Success ActionID: 1 EventList: start Message: Channel status will follow
Received pack: Event: StatusComplete ActionID: 1 EventList: Complete ListItems: 0 Items: 0
You should use callback method:
...
from asterisk.ami.action import SimpleAction
def callback_response(response):
print(response)
action = SimpleAction('Status')
client.send_action(action,callback=callback_response)
Please, read the documentation and examples on the main page.
Hello. I read documentation which said that I can use both syncronous and asyncronous requests. And even if I use call back, it still returns incomplete response.
Code
def test_action(action_name):
cl = AMIClient(**connection)
cl.login(**login)
act = SimpleAction(action_name)
fut = cl.send_action(act, callback=print_response)
cl.logoff()
def print_response(response):
print(response)
print(response.keys)
print(response.follows)
Output.
>>> from ami_t import *
>>> test_action('status')
Response: Success
ActionID: 1
EventList: start
Message: Channel status will follow
{'ActionID': '1', 'EventList': 'start', 'Message': 'Channel status will follow'}
[]
My fix of client.py which works for me.
54a55,62
> asterisk_start_list_regex = re.compile(
> b'^Response: Success\r\nActionID: \d+\r\nEventList: start',
> re.IGNORECASE | re.MULTILINE
> )
> asterisk_end_list_regex = re.compile(
> b'EventList: Complete\r\n.+\r\n.+\r\n\r\n',
> re.IGNORECASE | re.MULTILINE
> )
163c171,177
< while self.asterisk_pack_regex.search(data):
---
> is_list = self.asterisk_start_list_regex.match(data)
> list_ends = self.asterisk_end_list_regex.search(data)
> if is_list and list_ends:
> ending = list_ends.group()
> (pack, data) = self.asterisk_end_list_regex.split(data, 1)
> yield self._decode_pack(pack + ending)
> elif not is_list and self.asterisk_pack_regex.search(data):
165a180
>
I think you need add a event listener, because the events is not part os the response even though they had been generated by the action and announced by the response
I want make a "helper" to get the events that follows a response with EventList: start
but I'm without time these days
No. It is structure of complex response. And it returns an event list exactly.
AMIClient._next_pack handles responses wrong. It is expected that all events and responses are ended with a double CLRF what is wrong. There is no difference what I use, because _next_pack is the only "package generator".
I think, it may be that ActionCommand is decoded wrong too. I've not tested it yet.
I've wrote a solution that works, you can test.
Thank you, Kirill
On Wed, Nov 21, 2018 at 8:27 PM Éttore Leandro Tognoli < [email protected]> wrote:
I think you need add a event listener, because the events is not part os the response even though they had been generated by the action and announced by the response
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ettoreleandrotognoli/python-ami/issues/26#issuecomment-440727733, or mute the thread https://github.com/notifications/unsubscribe-auth/AMLpAUzbPVj0vXmTcJkIAD4tmQlC67qgks5uxX76gaJpZM4Ynqrh .
Ettore, no problem. I've faced a problem with locking client and switched to another library.
I'll make you a patch later on this week.
Thank you, Kirill
On Wed, Nov 21, 2018 at 8:35 PM Éttore Leandro Tognoli < [email protected]> wrote:
I want make a "helper" to get the events that follows a response with EventList: start but I'm without time these days
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ettoreleandrotognoli/python-ami/issues/26#issuecomment-440730395, or mute the thread https://github.com/notifications/unsubscribe-auth/AMLpAYEP-PaL7xXP4X5XX8ieInK2EeBWks5uxYDJgaJpZM4Ynqrh .
You have to distinguish between events which are responses to actions, and ones which are unsolicited. The EventList
header identifiers sequences of the former, which should all be treated as part of the response to the action.
You know how, on the Login
action, there is an Events
header? That’s where you specify whether you want to see unsolicited events or not.