Question

This my code to connect to Asterisk Manager Interface:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.IO;


namespace WindowsFormsApplication1
{

public partial class Form1 : Form
{

    private Socket clientSocket;
    private byte[] data = new byte[1024];
    private int size = 1024;
    //------------------------------------------------------------------------------------------
    public Form1()
    {
        InitializeComponent();            
    }

    //------------------------------------------------------------------------------------------
    [STAThread]
    private void BtnConnect_Click(object sender, EventArgs e)
    {
        try
        {
            AddItem("Connecting...");
            clientSocket = new Socket(AddressFamily.InterNetwork,
                                  SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.155"), 5038);
            clientSocket.BeginConnect(iep, new AsyncCallback(Connected), clientSocket);
        }
        catch (Exception exp)
        {

            AddItem(exp.Message);
        }
    }

    //------------------------------------------------------------------------------------------
    private void BtnDisconnect_Click(object sender, EventArgs e)
    {
        clientSocket.Close();
    }

    //------------------------------------------------------------------------------------------
    void Connected(IAsyncResult iar)
    {
        clientSocket = (Socket)iar.AsyncState;
        try
        {
            clientSocket.EndConnect(iar);
            AddItem("Connected to: " + clientSocket.RemoteEndPoint.ToString());                
            clientSocket.BeginReceive(data, 0, size, SocketFlags.None,
                          new AsyncCallback(OnDataReceive), clientSocket);
        }
        catch (Exception exp)
        {
            AddItem("Error connecting: " + exp.Message);
        }
    }
    //------------------------------------------------------------------------------------------

    private void OnDataReceive(IAsyncResult result)
    {
        Socket remote = (Socket)result.AsyncState;
        int recv = remote.EndReceive(result);
        string stringData = Encoding.ASCII.GetString(data, 0, recv);
        AddItem(stringData);
    }

    //------------------------------------------------------------------------------------------
    private delegate void stringDelegate(string s);
    private void AddItem(string s)
    {
        if (ListBoxEvents.InvokeRequired)
        {
            stringDelegate sd = new stringDelegate(AddItem);
            this.Invoke(sd, new object[] { s });
        }
        else
        {
            ListBoxEvents.Items.Add(s);
        }
    }

    //------------------------------------------------------------------------------------------
    private void BtnLogin_Click(object sender, EventArgs e)
    {
        clientSocket.Send(Encoding.ASCII.GetBytes("Action: Login\r\nUsername: admin\r\nSecret: lastsecret\r\nActionID: 1\r\n\r\n"));
    }

    //------------------------------------------------------------------------------------------


}
}

The problem is that when I connect to server I receive "Asterisk Call Manager/1.1" message. After connecting to the server I login to the server and I don't receive any message. I want to get events from asterisk. Is there a problem in using network Socket? Should I use a special command to tell asterisk that I want to receive events.

Was it helpful?

Solution

[edit]

Yeah. So this isn't a problem with AMI configuration.

You initiate a BeginReceive when your connection is finished - but once you've received data once, you don't initiate a new BeginReceive.

You'll need to call BeginReceive again in OnDataReceive, so that it attempts to read from the socket again.

clientSocket.BeginReceive(data, 0, size, SocketFlags.None,
                          new AsyncCallback(OnDataReceive), clientSocket);

I'm keeping my original answer below, as that information is still something you should check on. I'll reiterate my "FYI" again - unless you're doing this for educational purposes, you should really use an existing AMI library - particularly if you aren't familiar with TCP.

[original]

What username and password are you sending? Are you sure that account has been configured properly to send events?

Once you've authenticated your connection with Asterisk by logging in, you should start to automatically receive events. Keep in mind, however, that you'll need the appropriate Read authorization class permissions to receive events of certain types. From the sample manager.conf:

; Authorization for various classes
;
; Read authorization permits you to receive asynchronous events, in general.
; Write authorization permits you to send commands and get back responses.  The
; following classes exist:
;
; all       - All event classes below (including any we may have missed).
; system    - General information about the system and ability to run system
;             management commands, such as Shutdown, Restart, and Reload.
; call      - Information about channels and ability to set information in a
;             running channel.
; log       - Logging information.  Read-only. (Defined but not yet used.)
; verbose   - Verbose information.  Read-only. (Defined but not yet used.)
; agent     - Information about queues and agents and ability to add queue
;             members to a queue.
; user      - Permission to send and receive UserEvent.
; config    - Ability to read and write configuration files.
; command   - Permission to run CLI commands.  Write-only.
; dtmf      - Receive DTMF events.  Read-only.
; reporting - Ability to get information about the system.
; cdr       - Output of cdr_manager, if loaded.  Read-only.
; dialplan  - Receive NewExten and VarSet events.  Read-only.
; originate - Permission to originate new calls.  Write-only.
; agi       - Output AGI commands executed.  Input AGI command to execute.
; cc        - Call Completion events.  Read-only.
; aoc       - Permission to send Advice Of Charge messages and receive Advice
;           - Of Charge events.
; test      - Ability to read TestEvent notifications sent to the Asterisk Test
;             Suite.  Note that this is only enabled when the TEST_FRAMEWORK
;             compiler flag is defined.

So, say I wanted to authenticate as user "foo" with password "bar", with no ACLs defined, and I wanted to receive all events. I also only want to be able to execute 'system' and 'call' class commands. I would need to set up my user in manager.conf as:

[foo]
secret = bar
read = all
write = system,call

As an FYI - you may be re-inventing the wheel here. Unless you're creating your own AMI library as an exercise, you may want to consider using Asterisk .NET.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top