Skip to main content

This Python package performs external routing for Asterisk.

While Asterisk has an event-based interface (and a REST-based interface), it lacks a simple straightforward way to forward phone calls from A to B. Also, mangling phone numbers is rather awkward in Asterisk’s AEL.

This package is useful if you want to write your phone number mangling and rewriting in Python.

Installation

Install Asterisk and this module.

Create an appropriate configuration file.

Add this to extensions.ael:

// Your SIP calls arrive here. Add one of these for each SIP peer.
context in_foo {
    includes { default; };
    _[+0-9]. => &aroute(foo,${EXTEN});
}

context default {
    h => Hangup();
    i => Hangup();
}

macro aroute(src,ext) {
    Verbose(0,CALL: ${src}:${CALLERID(NUM)}:${ext});
    Set(curl=http://localhost:50080/route/${src}:${CALLERID(NUM)}:${ext});
    Verbose(0,    = ${CURL(${curl})});
    Set(dispatch=${CURL(${curl})});
    &get(hangup); Set(hangup=${res});
    if("${hangup}" = "") {
        &get(chan); Set(chan=${res});
        if("${chan}" = "Local") {
            &get(dest); Set(dest=${res});
            Set(dest=Local/${STRREPLACE(dest,+,@in_${src}&Local/)}@in_${src})
            Dial(${chan}/${dest});
        } else {
            &get(a_nr); Set(a_nr=${res});
            &get(b_nr); Set(b_nr=${res});
            &get(p_nr); Set(p_nr=${res});
            &get(end); Set(end=${res});

            Set(CALLERID(num)=${a_nr});
            Dial(${chan}/${b_nr}@${end});
        }
    } else {
        // error
        PJSIPHangup(${hangup});
    }
    Hangup();
    return;
}

macro get(name) {
    // extract a field from the CURL result.
    //
    // dispatch="foo=bar:baz=quux"
    // get(foo) -> bar
    //
    Set(disp=${dispatch});
    while("${disp}"!="") {
        Set(assign=${CUT(disp,:,1)});
        Set(disp=${CUT(disp,:,2-99)});

        Set(var=${CUT(assign,=,1)});
        Set(res=${CUT(assign,=,2)});
        if("${var}"=="${name}") {
            return;
        }

    }
    Set(res=);
    return;
}

Variables

This dialplan accepts these parameters:

  • a_nr number part of the caller id. This might need to be our SIP ID.

  • p_nr The real a_nr (SIP: P-Preferred-Identity)

  • b_nr Number to dial. This may need to be the destination SIP ID.

  • chan Channel. You probably want PJSIP. To divert to a local channel use “Local”.

  • dest Destination endpoint. This is the dialplan context when diverting to a local channel.

or

  • hangup PJSIP cause code.

For diverting a call to a local context, set chan=Local dest=context_name b_nr=extension.

Configuration

Bugs

hypercorn, which we use as an HTTP server, has an annoying bug in releases up to and including 0.17.3: it ignores a Connection: close header. This causes problems with clients like Icinga.

Zoom Phone integration

Get an API token from Zoom. It needs to be able to read your user records.

Create a secrets.yaml file:

zoom:
  # API to them
  account: "xxxxxxxxxxxxxxxxxxxxxx"
  client: "xxxxxxxxxxxxxxxxxxxxxx"
  password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

  # Sign replies to the callback from them
  # TODO
  #token: "xxxxxxxxxxxxxxxxxxxxxx"

Add something like this to your routing.yaml:

route:
- match: "496990009(0|[1-6]{2,3})"
  dest: zoom
  use: known
- match: "496990009(0|[1-6]{2,3})"
  dest: legacy_pbx

legacy_pbx:
    fallback: zoom

zoom:
    type: zoom
    fallback: legacy_pbx

    # Interval for updating extensions allocated on Zoom.
    # -1: read once (and when refreshing), 0: don't read at all
    update: 1200

    # Numbers to forward to Zoom, regardless of whether they are known
    known:
      - "496990009123"
    use: known  # only forward numbers that have been assigned

route:
  - match: "(0|[1-6][0-9]{2,3})"
    result: "496990009$1"
    dest: legacy_pbx

    a_in: false
    b_in: true

    a_out: null
    b_out: true
    p_out: false
    chan: "PJSIP"  # default
    # end: "zoom"  # endpoint. Default: provider name


zoom:
    # auth
    auth_url: https://zoom.us/oauth/token

    cred:
      # API
      account: !secret zoom.account
      client: !secret zoom.client
      secret: !secret zoom.password

      # callbacks
      #token: !secret zoom.token

The “fallback” causes a call that originates from this provider and gets routed back to the same provider to be routed to the fallback provider instead.

Release files for ast-route 0.9.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ast-route 0.9.2
File Size Uploaded
ast_route-0.9.2.tar.gz 130.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ast-route 0.9.2
File Interpreter ABI Platform
ast_route-0.9.2-py3-none-any.whl Python 3 none any Details

Total release size: 264.6 kB

Release files / ast_route-0.9.2.tar.gz

Download URL ast_route-0.9.2.tar.gz
Size 130.0 kB
Tags Source
SHA-256 checksum
How to use checksums
544ddd2314b3f0389a3fba698bb399191ad9f732a3016425d160ca14d631a87f
BLAKE2b-256 checksum
How to use checksums
c420b277ae5cd68c66a7c366e300fa67561295ec025a91d224f38b562198281d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.5

Release files / ast_route-0.9.2-py3-none-any.whl

Download URL ast_route-0.9.2-py3-none-any.whl
Size 134.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c97908950398d6be3314e31203920f77f6426075984ba1229358b44b81c781a3
BLAKE2b-256 checksum
How to use checksums
bd356b7899b86246d45a43985b289ac2227de80ebb39a893e7c60041422ff670
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

0.9.2 This release

2 release files

0.9.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page