python-ami icon indicating copy to clipboard operation
python-ami copied to clipboard

Incorrect pack deccoding on EventList.

Open soloma83 opened this issue 6 years ago • 7 comments

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

soloma83 avatar Nov 17 '18 22:11 soloma83

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.

romkazor avatar Nov 19 '18 23:11 romkazor

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
> 

soloma83 avatar Nov 21 '18 15:11 soloma83

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

ettoreleandrotognoli avatar Nov 21 '18 16:11 ettoreleandrotognoli

I want make a "helper" to get the events that follows a response with EventList: start but I'm without time these days

ettoreleandrotognoli avatar Nov 21 '18 16:11 ettoreleandrotognoli

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 .

soloma83 avatar Nov 21 '18 16:11 soloma83

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 .

soloma83 avatar Nov 21 '18 16:11 soloma83

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.

ldo avatar Dec 03 '22 02:12 ldo