Мы записываем вызовы вместе с записывающими 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()
Этот вопрос сложно решить. При исходящих вызовах 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.
Вот что я сделал, чтобы решить эту проблему. В настоящее время есть два драйвера 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 и все готово!
Это можно сделать без изменения источника.
Для этого вы должны использовать 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 в качестве ключа, после этого вы можете перехватить его в вашей диалплане звездочки.
Не забудьте документ решения в вашем проекте вики. Мой опыт говорит, что такие изменения (особенно в источниках звездочек) легко пропустить при восстановлении из резервной копии.