Как отправить мгновенное сообщение через SIP

У меня есть настольное приложение для Windows, сделанное моим провайдером мобильной сети, которое выполняет всевозможные действия с помощью SIP: вызов, отправка сообщения и т.д. Скриншот того, как это приложение успешно отправляет MESSAGE (последние 4 строки): Wireshark

MESSAGE запрос из настольного приложения отправляется как (4-я строка сзади):

MESSAGE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP LOCALIP:2112;branch=z9hG4bK-d8754z-905183245f478c76-1---d8754z-;rport
Max-Forwards: 70
To: "TO"<sip:[email protected]>
From: "FROM"<sip:[email protected]>;tag=63088d09
Call-ID: NGVhMDJhYzQwNmExOTQyNThmNjc5OGNmOTViNDUyYWM.
CSeq: 2 MESSAGE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO
Content-Type: text/plain
Content-Length: 4

test

и успешный ответ для этого:

SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP LOCALIP:2112;received=EXTERNALIP;branch=z9hG4bK-d8754z-905183245f478c76-1---d8754z-;rport=2112
To: "TO"<sip:[email protected]>;tag=c005f0e30133ec730add76fc91f4bea
From: "FROM"<sip:[email protected]>;tag=63088d09
Call-ID: NGVhMDJhYzQwNmExOTQyNThmNjc5OGNmOTViNDUyYWM.
CSeq: 2 MESSAGE
Content-Length: 0
Proxy-Authenticate: Digest nonce="3F178051B97E1F52000123000A3C53D4B",realm="DOMAIN",algorithm=MD5,qop="auth"

Затем я пытаюсь отправить идентичный (и n-варианты) запрос из PHP, но я всегда получаю SIP/2.0 403 Forbidden вместо SIP/2.0 407 Proxy Authentication Required:

SIP/2.0 403 Forbidden
Via: SIP/2.0/UDP LOCALIP;received=EXTERNALIP
To: "TO"<sip:[email protected]>;tag=aprqngfrt-f7ccjj0000020
From: "FROM"<sip:[email protected]>;tag=8f7be81d
Call-ID: [email protected]
CSeq: 1 MESSAGE
Reason: Q.850;cause=55;text="Call Terminated"
Content-Length: 0

Самое смешное, что если я отправлю запрос REGISTER, он работает, и я успешно получаю заголовок SIP/2.0 401 Unauthorized с WWW-Authenticate. Я пересчитываю авторизацию и повторно отправляю ее. Затем я получаю SIP/2.0 200 OK. Как это работает с MESSAGE.

Что может быть неправильным? Что я упустил? Запрос MESSAGE требует какого-либо другого запроса до этого (я уже пробовал REGISTER раньше)?
Я прочитал RFC 3428 вверх и вниз, попробовал все возможные примеры, но безуспешно.

Ответ 1

Если вы просмотрите полученный ответ 403, вы увидите заголовок Reason. Строка Q.850 в начале указывает, что это будет код причины, определяемый Рекомендацией МСЭ-Т.

В частности, приведенный код причины 55 связан с ISDN и литературными средствами "Входящие вызовы, запрещенные в пределах Закрытой группы пользователей" (вы можете проверить его в RFC 3398) и, как правило, означает, что в пределах группы участников вызов приема ограничен.

С другой стороны, причина 55 также указывает на проблему в запросе, особенно в отношении пользователя (отправителя или получателя). Следующая диаграмма показывает обычный обмен сообщениями между пользователями SIP:

      A             Server             B
      |    REGISTER    |               |
      |--------------->|               |
      |     200 OK     |               |
      |<---------------|               |
      |                |    REGISTER   |
      |                |<--------------|          
      |                |     200 OK    |
      |                |-------------->|
      |    MESSAGE     |               |
      |--------------->|    MESSAGE    |
      |                |-------------->|
      |                |     200 OK    |
      |                |<--------------|
      |     200 OK     |               |
      |<---------------|               |

На самом деле, был строгим, REGISTER от пользователя A не требуется, но большинство систем (например, IMS) использует его как механизм аутентификации. Затем в запросе REGISTER специальные заголовки:

Contact: <sip:[email protected]_IP:LOCAL_PORT>
Expires: REGISTRATION_DURATION

Имейте в виду, что 200 OK отвечает на REGISTER, может содержать заголовок Expires: или expires внутри заголовка Contact:, который указывает принятое время истечения срока действия. Например:

SIP/2.0 200 OK
...
Contact: <sip:[email protected]_IP:LOCAL_PORT>; expires=60 
...

В этой ситуации вы должны повторно зарегистрироваться до истечения этого срока (60 секунд в примере).

Помня о том, что вы пытаетесь отправить SMS на мобильный телефон, точка приема напрямую управляется вашим сетевым провайдером MGCF, поэтому это оставляет регистрацию отправителя или запрос MESSAGE.

О вашем исходном предложении MESSAGE, запросить URI (первая строка сообщения), должно быть:

 MESSAGE sip:[email protected] SIP/2.0

Потому что это относится к сущности приема MESSAGE.

Надеюсь, что это поможет.

Ответ 2

Как я уже сказал вам в комментариях, я не эксперт SIP, а мой друг. Я спросил его о вашем случае, и вот что он сказал мне:

Протокол SIP - это протокол диалога, означающий, что каждое сообщение представляет собой диалог с уникальным идентификатором диалога (что-то вроде идентификатора сеанса в HTTP). Разница между SIP и HTTP заключается в том, что идентификатор сеанса используется между различными соединениями TPC/IP (HTTP-запросы), в то время как идентификатор диалога используется в одном и том же соединении TPC/IP, но между различными сообщениями.

Мне кажется, что то, что вы пытаетесь сделать здесь, похоже на захват сеанса в HTTP. Хотя можно захватить идентификатор сеанса в HTTP и отправить его другому клиенту, то же самое не для SIP. Согласно моим друзьям, SIP-серверы имеют внутреннюю память, с которой идентификатор диалога принадлежит к тому соединению, и вы не можете пропустить ваши сообщения в чужой диалог, просто зная их идентификатор диалога.

В вашем вопросе не говорится, действительно ли это то, что вы пытаетесь сделать, но если это так, то я должен сказать, что вы не можете. Тот факт, что вы можете отправить команду REGISTER, показывает, что ваша связь с сервером SIP выполнена. Все, что вам нужно сделать, это начать свой собственный диалог и взять его оттуда.