Cause Data? Cause dados!
O libpri não é muito inteligente em indicar quais são os dados de causa no elemento de informação de causa (IE) - na verdade, a partir de 1.4.13, ele só lida com dois casos de cem dados em Q.850 ! Felizmente, não são apenas alguns dados diagnósticos proprietários aleatórios.
Referindo-se a Q.850 Uso de causa e localização ... , Tabela 1, precisamos verificar quais diagnósticos estão presentes para a causa 100 Conteúdo do elemento de informação inválido . E eis que é o identificador (es) do elemento de informação ! Então, IE 0x18 (24) da mensagem de Chamada Proceeding enviada pela libpri foi problemática. Por acaso, o IE 0x18 é o elemento do ID do canal. Então, pelo menos, sabemos que o problema está naquele elemento em particular. Para referência, aqui está a causa IE que recebemos da Cisco:
< [08 03 80 e4 18]
< Cause (len= 5) [ Ext: 1 Coding: CCITT (ITU) standard (0) Spare: 0 Location: User (0)
< Ext: 1 Cause: Invalid information element contents (100), class = Protocol Error (e.g. unknown message) (6) ]
< Cause data 1: 18 (24)
Identificação do Canal IE - Para Identificar ou Não
Agora que o restringimos a um IE, consulte Q.931 4.5.13 Identificação de canal [IE], notamos que o elemento inteiro é opcional ao responder a uma configuração de chamada se, como é o caso aqui, o equipamento do usuário simplesmente deseja usar o único canal explicitamente solicitado pela rede ( aqui: roteador Cisco).
Ai, a API interna da libpri para enviar a mensagem de continuação da chamada, q931_call_proceeding
em q931.c , não facilita muito o envio de um ID de canal completo. Na verdade, o struct q931_call
do libpri não retém o código de canal explícito mais recentemente recebido, por isso não há como decidir se o envio de um ID do canal IE é apropriado ou não. Heck, é um erro que call_proceeding_ies[]
contém Q931_CHANNEL_IDENT
- a mensagem de solicitação de chamada nem sempre requer este IE.
Então, uma correção seria simplesmente não enviar o ID do canal.
Mas o que é O Problema Dentro?
Infelizmente, podemos tentar aprofundar e verificar o que, no ID do canal, o IE alterou o firmware da Cisco.
Vamos comparar o ID do canal IE como recebido da Cisco e enviado novamente em resposta:
< [18 03 a9 83 81]
< Channel ID (len= 5) [ Ext: 1 IntID: Implicit Other(PRI) Spare: 0 Exclusive Dchan: 0
< ChanSel: As indicated in following octets
< Ext: 1 Coding: 0 Number Specified Channel Type: 3
< Ext: 1 Channel: 1 Type: CPE]
> [18 04 e9 81 83 81]
> Channel ID (len= 6) [ Ext: 1 IntID: Explicit Other(PRI) Spare: 0 Exclusive Dchan: 0
> ChanSel: As indicated in following octets
> Ext: 1 DS1 Identifier: 1
> Ext: 1 Coding: 0 Number Specified Channel Type: 3
> Ext: 1 Channel: 1 Type: CPE]
A diferença é bastante óbvia: o libpri responde com um octeto Identificador DS1 inteiramente gratuito. O Identificador DS1 é um identificador de um intervalo PRI específico a ser usado em sistemas que usam vários links. Isso não é necessário aqui, pois existe apenas um intervalo T1 entre o libpri e o roteador Cisco.
Isso parece ser um bug no firmware da Cisco - não há motivo para não aceitar o Identificador DS1 - é opcional, mas permitido pelo padrão. A menos que, é claro, o Identificador DS1 esteja de alguma forma errado - eu não investiguei isso.
O hack necessário para obter a libpri para jogar bola é um one-liner em transmit_channel_id
. Tudo o que precisamos fazer é suprimir a transmissão do octeto 3.1, o identificador DS1. Este patch faz isso:
--- libpri-1.4.14/q931.c.org 2013-04-16 15:22:24.910001979 -0400
+++ libpri-1.4.14/q931.c 2013-04-16 15:22:49.454001959 -0400
@@ -1441,7 +1441,7 @@
return 0;
}
- if (!ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
+ if (0 && !ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
/* We are specifying the interface. Octet 3.1 */
ie->data[pos++] |= 0x40;
ie->data[pos++] = 0x80 | call->ds1no;
Deve-se acrescentar que isso não é de forma alguma uma correção permanente para inclusão na libpri, apenas um hack temporário que exigiria alguns ajustes mais amplos para o libpri corrigir adequadamente.