Opened 4 years ago
Closed 4 years ago
#380 closed баг (fixed)
Гонки при доставке следующих за eCallEvent событий
| Reported by: | alx | Owned by: | alx |
|---|---|---|---|
| Priority: | средний | Milestone: | 1 очередь |
| Component: | any | Keywords: | |
| Cc: |
Description
При поступлении INVITE UAS создает объект CallData и привязывает его к вызову, затем генерирует широковещательное (ts == -1) событие eCallEvent. После обработки этого события канальным окончанием (если канальное окончание свободно и приняло решение обслужить вызов) вызов "привязывается" к конкретному окончанию установкой неотрицательного значения ts в CallData.
Может так случиться, что сразу вслед за INVITE приходят новые сообщения (например CANCEL), которые будут обработаны UAS (libeXosip2) до того как вызов будет "привязан" к конкретному окончанию. Созданные в результате события (eDisconnectEvent) тоже окажутся широковещательными (ts == -1). Но канальные окончания не рассчитаны на прием широковещательных eDisconnectEvent, поэтому такие события не будут обработаны, и канальное окончание останется в состоянии Connected.
Пример: имеем снятие вызова канального окончания FXO после "100 Trying":
04:45:59.689842 IP (tos 0x0, ttl 63, id 29456, offset 0, flags [+], proto UDP (17), length 1500)
192.168.1.67.5060 > 192.168.0.135.5060: SIP, length: 1472
INVITE sip:fxo@192.168.0.135 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.67:5060;branch=z9hG4bK-524287-1---30b25d5efc125300;rport
Via: SIP/2.0/UDP 127.0.0.1:6060;rport=6060;branch=z9hG4bK905542527
Max-Forwards: 69
Record-Route: <sip:192.168.1.67:5060;transport=udp;lr>
Contact: <sip:111@127.0.0.1:6060>
To: <sip:fxo@192.168.0.135>
From: "John West"<sip:111@192.168.1.67>;tag=655777206
Call-ID: 141332225
CSeq: 20 INVITE
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, REFER, NOTIFY, INFO, UPDATE, PRACK
Content-Type: application/sdp
Supported: replaces, timer, 100rel
User-Agent: eXosip/5.2.1
P-Asserted-Identity: "John West" <sip:111@192.168.1.67>
X-Endpoint-Type: FXS
Content-Length: 957
v=0
o=gateway 0 3 IN IP4 192.168.1.67
s=conversation
c=IN IP4 192.168.1.67
t=0 0
m=audio 10254 RTP/SAVP 8 0 4 18 101 98
a=altc:1 IP6 2a03:1ac0:2e92:d910:ad:c3ff:fe00:6 10254
a=altc:2 IP4 192.168.1.67 10254
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:t76pXJd0Z1ZY7UndIdHGpcCcou8Ddx+Mye8+uUEN
a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:pMSYCnil/YborXX9bNvA3+jBeVuO1iU5pDcC6U+z
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:4 G723/8000
a=fmtp:4 annexa=no
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=rtpmap:98 PCMA/8000
a=gpmd:98 vbd=yes
m=audio 10254 RTP/AVP 8 0 4 18 101 98
a=altc:1 IP6 2a03:1ac0:2e92:d910:ad:c3ff:fe00:6 10254
a=altc:2 IP4 192.168.1.67 10254
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a
04:45:59.793955 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 348)
192.168.0.135.5060 > 192.168.1.67.5060: SIP, length: 320
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.1.67:5060;branch=z9hG4bK-524287-1---30b25d5efc125300;rport=5060
Via: SIP/2.0/UDP 127.0.0.1:6060;rport=6060;branch=z9hG4bK905542527
To: <sip:fxo@192.168.0.135>
From: "John West"<sip:111@192.168.1.67>;tag=655777206
Call-ID: 141332225
CSeq: 20 INVITE
Content-Length: 0
04:45:59.805828 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 311)
192.168.1.67.5060 > 192.168.0.135.5060: SIP, length: 283
CANCEL sip:fxo@192.168.0.135 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.67:5060;branch=z9hG4bK-524287-1---30b25d5efc125300;rport
Max-Forwards: 70
To: <sip:fxo@192.168.0.135>
From: "John West"<sip:111@192.168.1.67>;tag=655777206
Call-ID: 141332225
CSeq: 20 CANCEL
Content-Length: 0
04:45:59.821022 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 311)
192.168.0.135.5060 > 192.168.1.67.5060: SIP, length: 283
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.67:5060;branch=z9hG4bK-524287-1---30b25d5efc125300;rport=5060
To: <sip:fxo@192.168.0.135>;tag=86c52c75
From: "John West"<sip:111@192.168.1.67>;tag=655777206
Call-ID: 141332225
CSeq: 20 CANCEL
Server: repro 1.12.0
Content-Length: 0
04:45:59.866586 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 423)
192.168.0.135.5060 > 192.168.1.67.5060: SIP, length: 395
SIP/2.0 487 Request Terminated
Via: SIP/2.0/UDP 192.168.1.67:5060;branch=z9hG4bK-524287-1---30b25d5efc125300;rport=5060
Via: SIP/2.0/UDP 127.0.0.1:6060;rport=6060;branch=z9hG4bK905542527
To: <sip:fxo@192.168.0.135>;tag=634931166
From: "John West" <sip:111@192.168.1.67>;tag=655777206
Call-ID: 141332225
CSeq: 20 INVITE
Server: repro 1.12.0
User-Agent: eXosip/5.2.1
Content-Length: 0
04:45:59.875832 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 319)
192.168.1.67.5060 > 192.168.0.135.5060: SIP, length: 291
ACK sip:fxo@192.168.0.135 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.67:5060;branch=z9hG4bK-524287-1---30b25d5efc125300;rport
Max-Forwards: 70
To: <sip:fxo@192.168.0.135>;tag=634931166
From: "John West"<sip:111@192.168.1.67>;tag=655777206
Call-ID: 141332225
CSeq: 20 ACK
Content-Length: 0
В результате FXO осталось в состоянии Connected. Вот лог:
sip_ua[688]: repro.cpp:582: doSessionAccounting(): Session Created 'branch=z9hG4bK-524287-1---c392fc2efcccfd42' sip_ua[688]: repro.cpp:757: doSessionAccounting(): Session Cancelled 'branch=z9hG4bK-524287-1---c392fc2efcccfd42' sip_ua[654]: user_agent.cpp:2098: ---> transport 0: SIP event 2 (New call received!): cid=15, did=16, tid=16, rid=0, sid=0, nid=0 sip_ua[654]: user_agent.cpp:2225: INVITE received: sip:fxo@127.0.0.1:6060;transport=udp (Call-ID: 134475806@(null)) sip_ua[629]: ss7.cpp:1661: ---> SS7[2]: Incoming call, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[3]: Incoming call, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[4]: Incoming call, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[5]: Incoming call, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[6]: Incoming call, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[7]: Incoming call, ts=-1, flags=0001, data=15 sip_ua[629]: fxs.cpp:432: ---> ts=8, state=Idle: Incoming call, ts=-1, flags=0001, data=15 sip_ua[629]: fxo.cpp:343: ---> ts=9, state=Idle: Incoming call, ts=-1, flags=0001, data=15 sip_ua[654]: user_agent.cpp:2098: ---> transport 0: SIP event 13 (Call has been cancelled!): cid=15, did=16, tid=17, rid=0, sid=0, nid=0 sip_ua[654]: user_agent.cpp:2098: ---> transport 0: SIP event 21 (Bye Received!): cid=15, did=-1, tid=16, rid=0, sid=0, nid=0 sip_ua[629]: user_agent.cpp:4051: Call 15 routed to TS 9 sip_ua[629]: ss7.cpp:1661: ---> SS7[2]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[3]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[4]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[5]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[6]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[7]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: fxs.cpp:432: ---> ts=8, state=Idle: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: fxo.cpp:343: ---> ts=9, state=Connected: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[2]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[3]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[4]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[5]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[6]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[7]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: fxs.cpp:432: ---> ts=8, state=Idle: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: fxo.cpp:343: ---> ts=9, state=Connected: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[2]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[3]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[4]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[5]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[6]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[7]: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: fxs.cpp:432: ---> ts=8, state=Idle: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: fxo.cpp:343: ---> ts=9, state=Connected: Call disconnected, ts=-1, flags=0001, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[2]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[3]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[4]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[5]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[6]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: ss7.cpp:1661: ---> SS7[7]: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: fxs.cpp:432: ---> ts=8, state=Idle: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: fxo.cpp:343: ---> ts=9, state=Connected: Call disconnected, ts=-1, flags=0002, data=15 sip_ua[629]: fxo.cpp:343: ---> ts=9, state=Connected: CAS event, ts=9, flags=0000, data=5 sip_ua[629]: user_agent.cpp:4026: eXosip_call_build_answer(-1, 200) error -3 sip_ua[629]: user_agent.cpp:4032: ua_response_status(15, 200) error -2 sip_ua[629]: comcerto.cpp:6180: channel 9: answer
Здесь видно, что SIP event 13 (Call has been cancelled!) и SIP event 21 (Bye Received!) были обработаны до того как уже наше событие eCallEvent выло обработано канальным окончанием и вызов был "закреплен" за конкретным канальным окончанием. Как результат - два события eDisconnectEvent оказались широковещательными.
Варианты решения проблемы:
- В CallData организовать отдельную очередь событий, и все следующие за eCallEvent события складывать в эту очередь, откладывая их доставку до момента, когда обработка eCallEvent будет закончена.
- Механизм доставки событий оставить как есть, гл в каждом канальном окончании сделать обработку широковещательных событий eDisconnectEvent, которые матчить только по Call Id (event->data).
- Следующие за INVITE собятия помещать в общую очередь, как это и происходит сейчас, но по окончании обработки eCallEvent, если вызов был прикреплен к канальному окончанию, модифицировать поле ts уже находящихся в очереди событий с таким же Call Id (event->data).
На первый взгляд, самым простым будет вариант 2.

In 1977/sip_ua: