Skip to content

xivo/asterisk: allow dots in channel interfaces - #191

Merged
wazo-community-zuul[bot] merged 2 commits into
masterfrom
ITEM-613-invalidchannelerror-dot-exten
Aug 26, 2026
Merged

wazo-community-zuul[bot] merged 2 commits into
masterfrom
ITEM-613-invalidchannelerror-dot-exten

Conversation

@bloom1

@bloom1 bloom1 commented Aug 20, 2026

Copy link
Copy Markdown
Member

The interface character class rejected ., so any channel whose exten or context contains a dot failed to match and raised InvalidChannelError. Sanitized examples of the two reported shapes:

Local/.98@default-key-0000-internal-00003196;1
Local/01.23.45.67.89@default-key-xxxxx-internal-00006c75;1

The second is a French number dialed with dot separators, which is how the partner reported it (BUG-123 / WP-1576).

In wazo-call-logd this is reached through _remove_duplicate_participants(). It used to abort the whole wazo-call-logs run, which is what the reported traceback shows; since the per-linkedid try/except it only drops the affected group, so those calls now silently produce no CDR instead.

. joins *, +, # and |, which were each added the same way. Backtracking is unchanged: the interface still resolves to exten@context, splitting at the last - before the uniqueid.

device_regexp has the same gap but is left alone here: it parses dialplan hints, and it uses .match() rather than .search(), so a dotted value truncates silently rather than raising.


Note

Medium Risk
Shared channel parsing regex changes how real Asterisk channel names are accepted or rejected, which affects downstream call-log/CDR flows; behavior is tightened at the end anchor but broadened for resource characters.

Overview
Fixes InvalidChannelError for Asterisk channel strings whose resource (exten/context) contains dots or other characters outside the old channel_regexp class—including reported Local/.98@… and dot-separated French number shapes.

channel_regexp is rewritten to treat the resource as unconstrained (.+) and to anchor the suffix as either the usual -<hex uniqueid> (optional ;<leg> for Local) or WebSocket’s /0x<pointer>. websocket is added as a technology. Inline comments document how drivers build channel names.

Channels without a valid discriminator (e.g. PJSIP/my-line) are now explicitly rejected. device_regexp is unchanged in this PR.

Tests cover dots, dotted numbers, IAX2 resources with %/!, WebSocket channels, and missing uniqueids.

Reviewed by Cursor Bugbot for commit 593ec55. Bugbot is set up for automated code reviews on this repo. Configure here.

The interface character class rejected `.`, so any channel whose exten or
context contains a dot failed to match and raised InvalidChannelError.
Sanitized examples of the two reported shapes:

    Local/.98@default-key-0000-internal-00003196;1
    Local/01.23.45.67.89@default-key-xxxxx-internal-00006c75;1

The second is a French number dialed with dot separators, which is how the
partner reported it (BUG-123 / WP-1576).

In wazo-call-logd this is reached through _remove_duplicate_participants().
It used to abort the whole wazo-call-logs run, which is what the reported
traceback shows; since the per-linkedid try/except it only drops the
affected group, so those calls now silently produce no CDR instead.

`.` joins `*`, `+`, `#` and `|`, which were each added the same way.
Backtracking is unchanged: the interface still resolves to exten@context,
splitting at the last `-` before the uniqueid.

device_regexp has the same gap but is left alone here: it parses dialplan
hints, and it uses .match() rather than .search(), so a dotted value
truncates silently rather than raising.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bloom1 bloom1 added the mergeit label Aug 20, 2026
@notion-workspace

Copy link
Copy Markdown

@wazo-community-zuul

Copy link
Copy Markdown
Contributor

Build succeeded.
https://zuul.wazo.community/zuul/t/local/buildset/bdb286bc01c84136a48835784244ccb7

✔️ wazo-tox-py311 SUCCESS in 2m 52s
✔️ tox-linters SUCCESS in 2m 31s
✔️ wazo-tox-integration-py311 SUCCESS in 6m 31s
✔️ debian-packaging-bookworm SUCCESS in 2m 12s

@DrPyser

DrPyser commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

I propose generalizing the regex to concern itself with the relevant expectations on channel syntax.

channel_regexp = re.compile(
    r'(pjsip|sip|sccp|local|dahdi|iax2)/(.+)-\d+(?:;\d+)?$',
    re.I,
)
(use re.match instead of re.search since we match the whole string)

https://regex101.com/?regex=%28pjsip%7Csip%7Csccp%7Clocal%7Cdahdi%7Ciax2%29%2F%28.%2B%29-%5Cd%2B%28%3F%3A%3B%5Cd%2B%29%3F%24&testString=PJSIP%2Fabcdefgh-00000001%0ALocal%2F1002.%40default-00000001%3B1%0ADAHDI%2Fi1%2F5551234-1%0AIAX2%2Fuser%4010.0.0.1%3A4569-1%0APJSIP%2Fmy-line&flags=gmi&flavor=pcre2&delimiter=%25

The important requirements based on existing usages (wazo-calld, wazo-call-logd):

  • correctly extracts the "protocol" (channel type) prefix string
  • extracts the protocol-specific interface resource identifier while dismissing channel identifier suffix (e.g. -00000000001) and local leg identifier suffix (e.g. ;1)

We don't need to constraint the character set of the endpoint resource, and we don't need to know all the possible formats of channel-type-specific resources, as long as we can distinguish the identifier of the endpoint and the channel-specific suffixes.

My suggestion: try this regex against existing test cases in xivo-lib-python. To be safe, we can run wazo-calld and wazo-call-logd integration tests against this PR as well (dummy PRs with depends-on).

@DrPyser

DrPyser commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Also note: we'll eventually want to support the WebSocket protocol, whose channels take the form WebSocket/connection1/0x559011d64c80 or similar. This will involve adding to the regex as well.
With my proposed form, we could just add WebSocket to the protocol prefix alternative list right now and that would be done.

Rather than whitelisting the characters a channel resource may contain --
a list that has grown one fix at a time, most recently for dots -- match
on the structure Asterisk actually guarantees: the technology prefix, and
the discriminator each channel driver appends to make the name unique.
Whatever lies between them is the resource, unconstrained.

The discriminator is per-driver, not central; ast_channel_alloc takes it
as name_fmt from the caller. Anchoring on it means -<uniqueid> in hex
(PJSIP and Local '%08x', DAHDI '%x', IAX2 a decimal call number), plus
;<leg> for the two halves of a local channel, and /%p for chan_websocket,
which appends the channel pointer after a slash instead of a uniqueid.

Requiring the discriminator makes the match stricter than before: a
suffix-less string such as PJSIP/my-line now raises InvalidChannelError
where it used to yield the truncated interface 'my'.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@wazo-community-zuul

Copy link
Copy Markdown
Contributor

Build succeeded.
https://zuul.wazo.community/zuul/t/local/buildset/83a1b17ceb2e4bcbab10ff5564827f04

✔️ wazo-tox-py311 SUCCESS in 2m 34s
✔️ tox-linters SUCCESS in 2m 30s
✔️ wazo-tox-integration-py311 SUCCESS in 6m 16s
✔️ debian-packaging-bookworm SUCCESS in 2m 14s

@bloom1

bloom1 commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

I propose generalizing the regex to concern itself with the relevant expectations on channel syntax.

channel_regexp = re.compile(
    r'(pjsip|sip|sccp|local|dahdi|iax2)/(.+)-\d+(?:;\d+)?$',
    re.I,
)
(use re.match instead of re.search since we match the whole string)

https://regex101.com/?regex=%28pjsip%7Csip%7Csccp%7Clocal%7Cdahdi%7Ciax2%29%2F%28.%2B%29-%5Cd%2B%28%3F%3A%3B%5Cd%2B%29%3F%24&testString=PJSIP%2Fabcdefgh-00000001%0ALocal%2F1002.%40default-00000001%3B1%0ADAHDI%2Fi1%2F5551234-1%0AIAX2%2Fuser%4010.0.0.1%3A4569-1%0APJSIP%2Fmy-line&flags=gmi&flavor=pcre2&delimiter=%25

The important requirements based on existing usages (wazo-calld, wazo-call-logd):

  • correctly extracts the "protocol" (channel type) prefix string
  • extracts the protocol-specific interface resource identifier while dismissing channel identifier suffix (e.g. -00000000001) and local leg identifier suffix (e.g. ;1)

We don't need to constraint the character set of the endpoint resource, and we don't need to know all the possible formats of channel-type-specific resources, as long as we can distinguish the identifier of the endpoint and the channel-specific suffixes.

My suggestion: try this regex against existing test cases in xivo-lib-python. To be safe, we can run wazo-calld and wazo-call-logd integration tests against this PR as well (dummy PRs with depends-on).

Did the fixes and ran tests on both repos. Had to fix 3 tests fixtures in wazo-call-logd because the format used was invalid: wazo-platform/wazo-call-logd#301

@DrPyser DrPyser left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, tested on my stack and could validate that . and WebSocket channels do not produce errors anymore.
Only channels in form "CLIEval/2" produce InvalidChannelError, but that does not matter for now (those are channels resulting from asterisk CLI function evaluation for debugging purposes).

Thank you! Hopefully we stop seeing that kind of issues.

@wazo-community-zuul

Copy link
Copy Markdown
Contributor

Build succeeded (gate pipeline).
https://zuul.wazo.community/zuul/t/local/buildset/b4c5d0ccb5f643b9a3a6caedea8fcfe8

✔️ wazo-tox-py311 SUCCESS in 2m 40s
✔️ tox-linters SUCCESS in 2m 35s
✔️ wazo-tox-integration-py311 SUCCESS in 6m 57s
✔️ debian-packaging-bookworm SUCCESS in 2m 24s

@wazo-community-zuul
wazo-community-zuul Bot merged commit e48d6f6 into master Aug 26, 2026
3 checks passed
@wazo-community-zuul
wazo-community-zuul Bot deleted the ITEM-613-invalidchannelerror-dot-exten branch August 26, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants