Вопрос или проблема
Я пытаюсь создать SIP-клиент, который записывает все входящие звонки. Я использую Python и библиотеку pyVoIP, вот код:
from pyVoIP.VoIP import VoIPPhone, CallState, PhoneStatus, InvalidStateError
import time
import datetime
def answer(call): # Это функция обратного вызова, которая срабатывает при получении телефонного звонка
try:
print(call.state)
anum = call.request.headers["From"]["number"]
print(',' + datetime.datetime.now().strftime("%Y%m%d") + ', ' + datetime.datetime.now().strftime("%X") + ', ' + datetime.datetime.now().strftime("%f") + ',,,,,,,' + anum + ',0662279775,,,')
open('tmp.csv', 'w+')
f.write(',' + datetime.datetime.now().strftime("%Y%m%d") + ', ' + datetime.datetime.now().strftime("%X") + ', ' + datetime.datetime.now().strftime("%f") + ',,,,,,,' + anum + ',0662279775,,,')
print(anum)
call.answer()
call.hangup()
except InvalidStateError:
print(InvalidStateError)
pass
if __name__ == "__main__":
vp = VoIPPhone('79.98.45.133', 5060, '0662279775', '065+eMl6Ttd6$T', callCallback=answer)
print('VOIP PHONE ИНИЦИАЛИЗИРОВАН: статус="' + str(vp._status))
vp.start()
print("VoIP PHONE ЗАПУЩЕН: статус=" + str(vp._status))
while(vp._status == PhoneStatus.REGISTERING or vp._status == PhoneStatus.INACTIVE):
continue
print("STATUS ЦИКЛА WHILE ЗАВЕРШЕН: статус=" + str(vp._status))
input("Нажмите ENTER, чтобы остановить")
time.sleep(5)
vp.stop()
print('VOIP PHONE ОСТАНОВЛЕН: статус="' + str(vp._status))
time.sleep(5)
Фаза регистрации проходит успешно, клиент может зарегистрироваться на SIP-сервере, и я получаю:
STATUS ЦИКЛА WHILE ЗАВЕРШЕН: статус = PhoneStatus.REGISTERED
Когда я перезваниваю на номер, связанный с SIP-аккаунтом, иногда звонок принимается клиентом, а иногда нет. Я сделал трассировку SIP-пакета, полученного клиентом, и вижу, что SIP-сервер отправляет сообщения OPTIONS клиенту, но клиент не отвечает на них. Я предполагаю, что в этом проблема: сервер не получает ответа на сообщения OPTIONS, поэтому считает, что клиент неактивен и не перенаправляет звонок клиенту.
Есть ли способ настроить pyVoIP для ответа на сообщения OPTIONS?
Ответ или решение
Ваша проблема действительно может быть связана с тем, что клиент PyVoIP не отвечает на SIP OPTIONS сообщения, отправляемые SIP-сервером. Это может вызвать проблемы с поддержанием статуса регистрации клиента, в результате чего сервер может считать клиента недоступным, не перенаправляя вызовы. Рассмотрим, как можно решить эту проблему.
1. Обработка SIP OPTIONS
В библиотеке PyVoIP не всегда непосредственно предусмотрена обработка SIP OPTIONS, поэтому вам нужно убедиться, что клиент отвечает на эти сообщения. Можно добавить собственную обработку сообщений, в том числе для OPTIONS. Вам нужно будет создать метод для обработки входящих SIP-сообщений и определить, как реагировать на OPTIONS.
Вот пример кода, который показывает, как можно обработать SIP OPTIONS:
from pyVoIP.VoIP import VoIPPhone, CallState, PhoneStatus, InvalidStateError
import time
import datetime
def handle_incoming_message(message):
if message.method == 'OPTIONS':
# Отправляем ответ на OPTIONS
response = message.create_response(200, "OK")
message.send_response(response)
def answer(call):
try:
print(call.state)
anum = call.request.headers["From"]["number"]
print(',' + datetime.datetime.now().strftime("%Y%m%d") + ', ' + datetime.datetime.now().strftime("%X") + ', ' + datetime.datetime.now().strftime("%f") + ',,,,,,,' + anum + ',0662279775,,,')
with open('tmp.csv', 'a') as f:
f.write(',' + datetime.datetime.now().strftime("%Y%m%d") + ', ' + datetime.datetime.now().strftime("%X") + ', ' + datetime.datetime.now().strftime("%f") + ',,,,,,,' + anum + ',0662279775,,,\n')
print(anum)
call.answer()
call.hangup()
except InvalidStateError as e:
print(e)
pass
if __name__ == "__main__":
vp = VoIPPhone('79.98.45.133', 5060, '0662279775', '065+eMl6Ttd6$T',
callCallback=answer, messageCallback=handle_incoming_message)
print('VOIP PHONE INITIALIZED: status=' + str(vp._status))
vp.start()
print("VoIP PHONE STARTED: status=" + str(vp._status))
while (vp._status == PhoneStatus.REGISTERING or vp._status == PhoneStatus.INACTIVE):
continue
print("WHILE LOOP STATUS ENDED: status=" + str(vp._status))
input("Press ENTER to stop")
time.sleep(5)
vp.stop()
print('STOPPED VOIP PHONE: status=' + str(vp._status))
time.sleep(5)
2. Обратите внимание на следующее:
- Использование
create_response
: В коде вы должны создать ответ на OPTIONS с помощью методаcreate_response
, передав корректные код и текст ответа. - Логика обработки сообщений: Убедитесь, что сообщения, которые ваш клиент принимает, проверяются на предмет метода OPTIONS. Это предположение может быть дополнительно уточнено в зависимости от специфики библиотеки.
- Отключение из
register
: Не забудьте запускать методvp.stop()
корректно, чтобы не вызвать потенциальные утечки ресурсов.
3. Рекомендации
-
Документация
Поскольку библиотека PyVoIP не является широко распространенной, обязательно обращайтесь к ее документации для получения информации о возможностях и примерах использования. -
Отладка:
Используйте пакетный анализатор, такой как Wireshark, чтобы убедиться, что ваш клиент действительно не отвечает на OPTIONS и отслеживать весь SIP-трафик для дальнейших шагов отладки.
Следуя приведенным рекомендациям, вы сможете убедиться, что ваш SIP-клиент отвечает на OPTIONS сообщения и решает вашу проблему с недоступностью.