Нужна помощь в получении Twilio X-Twilio-CallSid или X-Twilio-RecordingSid на исходящие звонки

Мы записываем вызовы вместе с записывающими Sid Twilio в базу данных, и поскольку Asterisk выставляет sip-заголовки Twilio только на диалплан по запросам (в отличие от ответов), мы не можем получить заголовки X-Twilio-CallSid и X-Twilio-RecordingSid на канал дальнего конца.

На вызов, исходящий из локального добавочного номера Twilio и прерванный исходящим добавочным номером, когда сообщение BYE приходит от нас локально, все, что Asterisk когда-либо видит, это SIP-ответы.

Кто-нибудь может помочь получить CallSid или RecordingSid доступными через диалплан или скрипт PHP AGI?

Мы попытались вставить подпрограмму gosub на вызываемом канале (дальний конец), что позволило нам получить доступ к переменным на этом канале, но доступные заголовки SIP доступны только из сообщения INVITE от Asterisk. Ни один из заголовков ответов Twilio никогда не раскрывается. UNLESS Twilio отправляет запрос BYE, и в этом случае обработчик отбоя выставит CallSid и RecordingSid. Однако, если Asterisk вешает вызов, сообщение BYE, сгенерированное Asterisk, запускает обработчик отбоя до того, как требуемые заголовки ответа Twilio SIP будут получены звездочкой.

PHP AGI DialScript с подпрограммой gosub.

$agi->exec("Dial", "SIP/twilio-out/+1$call->dnid,180,rU(far-channel-hangup-hook,".$call->calllog_listid.")");

Настройка Dial-Plan (extensions.conf)

[far-channel-hangup-hook]
exten => s,1,Set(calllog_listid=${ARG1})
exten => s,n,Set(CHANNEL(hangup_handler_push)=far-channel-hangup,s,1)
exten => s,n,Return()

[far-channel-hangup]
exten => _.!,1,AGI(log_sid.php)
exten => _.!,n,Return()

1

Решение

Этот вопрос сложно решить. При исходящих вызовах Twilio сначала предоставляет CallSid в ответе 200 OK на ваше первоначальное сообщение INVITE. Поскольку это всего лишь ответ, Asterisk не позволит вам получить доступ к заголовку SIP через SIP_HEADER ().

Вы правы, если Asterisk инициирует вызов, вы можете установить обработчик зависания, который будет срабатывать при завершении вызова, и если Twilio отправит BYE, у вас будет полный доступ к заголовкам «X-Twilio» в вашем обработчике , но НЕ, если Asterisk завершает вызов своим собственным BYE. Тем не менее, если вы когда-нибудь сможете извлечь Twilio-CallSid из Asterisk в течение жизни диалога, вы можете использовать cURL в зависание-обработчик чтобы получить больше информации о записанном звонке на основе CallSid.

Twilio документация объясняет, что вы можете отправить HTTP-запрос GET с CallSid к их API записей и получить информацию о записи.

curl -X GET -https://video.twilio.com/v1/Recordings/RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' -u ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token

В своем коде PHPAGI вы можете сделать что-то вроде этого:

    $recording_object = NULL;
$accountsid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
$auth_token = "xxxxxxxxxxxxxxxxxxx"; // Your API access auth token
$cidurl = "https://api.twilio.com/2010-04-01/Accounts/$accountsid/Calls/$CallSid/Recordings.json";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $cidurl);
curl_setopt($ch, CURLOPT_USERPWD, "$accountsid:$auth_token");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$retval = curl_exec($ch);
$obj = json_decode($retval);
curl_close($ch);
if ($obj) {
if (property_exists($obj, "recordings")) {
$recording_object = $obj->recordings;
}
}

И вы сможете получить доступ к RecordingSid и RecordingDuration через:

    $recording_object->sid

а также

    $recording_object->duration

(Если $ recording_object не равен NULL)

Теперь, чтобы на самом деле получить X-Twilio-CallSid ранее в вызове (диалог SIP), пришло еще больше хитрости.

Я всегда строю Asterisk из исходного кода. Это очень просто. Существуют даже сценарии для установки зависимостей для вас на основе репозитория вашего Linux Distro.

Вот пример для CentOS.

Вот что я сделал, чтобы решить эту проблему. В настоящее время есть два драйвера SIP-канала, которые поставляются с Asterisk «chan_sip» и «chan_pjsip». Я использую chan_sip, более старый (зрелый, проверенный и верный) драйвер канала. Это работает хорошо.

Если вы загружаете исходный код для Asterisk и перед тем, как выполнить действия, описанные в вышеупомянутом руководстве, найдите файл «chan_sip.c». Обычно это в каталоге / каналы

Отредактируйте файл.

Внутри файла есть функция handle_response ().

/*! \brief Handle SIP response in dialogue
\note only called by handle_incoming */
static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)

Ищите эту функцию.

Внутри этой функции ищите первый переключатель оператор, а затем следуйте коду, где у вас есть условие «case 200:».

Это должно выглядеть примерно так:

    case 200:   /* 200 OK */
p->authtries = 0;   /* Reset authentication counter */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_REGISTER) {
handle_response_register(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_SUBSCRIBE) {
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
handle_response_subscribe(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_BYE) {      /* Ok, we're ready to go */
pvt_set_needdestroy(p, "received 200 response");
ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
}
break;

Измените это, чтобы выглядеть так:

    case 200:   /* 200 OK */
p->authtries = 0;   /* Reset authentication counter */
if (sipmethod == SIP_INVITE) {
const char *twilio_callsid = sip_get_header(req, "X-Twilio-CallSid");
if (twilio_callsid) {
ast_verb(1, "** Setting channel variable 'twiliocallsid' to '%s'\n", twilio_callsid);
pbx_builtin_setvar_helper(owner, "twiliocallsid", twilio_callsid);
}
handle_response_invite(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_REGISTER) {
handle_response_register(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_SUBSCRIBE) {
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
handle_response_subscribe(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_BYE) {      /* Ok, we're ready to go */
pvt_set_needdestroy(p, "received 200 response");
ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
}
break;

Сохраните файл. Затем следуйте инструкциям по сборке и установке Asterisk.

Теперь, как только Twilio ответит на INVITE и отправит 200 OK который будет содержать X-Twilio-CallSid chan_sip установит его как переменная канала называется «twiliocallsid», и он будет доступен из абонентской группы ИЛИ вашего сценария PHPAGI. Вы можете получить CallSid и использовать его в своем запросе cURL к Twilio, чтобы получить информацию о записи и сохранить ее по своему желанию.

Я не совсем уверен в этом, но если вы уже установили Asterisk, вы может быть все равно сможете его выключить, перейдите в каталог с исходным кодом и запустите «make install». Кто-то еще может внести свой вклад в это, но когда вы собираете и устанавливаете его из исходного кода, это все, что нужно. Вы можете изменить исходный код так, как вам нужно, и скомпилировать то, что было изменено, с помощью команды «make install».

Затем остановитесь, перезапустите Asterisk и все готово!

1

Другие решения

Это можно сделать без изменения источника.

Для этого вы должны использовать iptables action NLOG.

Что-то вроде этого

iptables -I INPUT -p udp --dport 5060 -m string --string "X-Twilio-" --algo bm -j NFLOG

После этого вам нужно прочитать скриптом nflog, разобрать его, сохранить запись где-нибудь и перехватить ее.

tcpdump -i nflog -s0 -vvv -n|script here

Скрипт может сохранять результаты в memcached или mysql, используя callid в качестве ключа, после этого вы можете перехватить его в вашей диалплане звездочки.

Не забудьте документ решения в вашем проекте вики. Мой опыт говорит, что такие изменения (особенно в источниках звездочек) легко пропустить при восстановлении из резервной копии.

0

По вопросам рекламы [email protected]