PJSUA Function Flow-SIP
pjproject-2.5의 pjsua의 오퍼레이션을 소스레벨에서 추적해 본다. PJSIP Developer’s Guide를 중심으로 전화를 수신했을때 수행되는 함수의 흐름을 따라간다.
1. app_init 의 오퍼레이션 절차
- pjsip-apps/src/pjsua/pjsua_app.c
- pjsua 생성(endpoint 생성)
- 응용프로그램용 pool 생성
- CLI 및 FE 설정
- 설정 파라미터 파싱
- 각종 전화상태에 따른 콜백함수 등록(on_call_state, on_incoming_call 등)
- 오디오 장치의 캡춰 및 재생의 레이턴시 설정
- pjsua 초기화 : pjsua_init()
- pjsua_media_subsys_init(): work thread 생성(media): pjmedia_endpt->ioqueue RTP 폴링
- work thread 생성(pjsua_0) : pjsip_endpoint->ioqueue SIP message 폴링
- endpoint에 module 등록
- 디폴트 모듈을 등록하고 나머지 모듈은 아래에서 등록한다.
- pjsip-simple/mwi.c - mod_mwi
- pjsip-simple/presence.c - mod_presence
- pjsip-ua/sip_100rel.c - mod_100rel.mod
- pjsip-ua/sip_inv.c - mod_inv.mod
- pjsip-ua/sip_xfer.c - mod_xfer
- pjsip/sip_transaction.c - mod_tsx_layer.mod, mod_stateful_uitl, mod_msg_prit 등록
- pjsip/sip_ua_layer.c - mod_ua.mod 등록
- pjsua-lib/pjsua_core - pjsua_msg_logger, pjsua_var.mod, pjsua_options_handler 등록
- pjsua-lib/pjsua_im.c - mod_pjsua_im
- pjsua-lib/pjsua_pres.c - pjsua_unsolicited_mwi_mod
- 옵션사항으로 WAV파일 등록
- 옵션사항으로 tone 재생기등록
- 옵션사항으로 레코딩 파일 등록
- Ringback(발신벨소리) 및 Ring(수신벨소리) 생성
- AVI 재생기 생성
- UDP 전송포트, 생성
- pjsua_transport_create() -> pjsip_udp_transport_attach2() ->
- transport_attach() -> register_to_ioqueue()
- ioqueue_cb.on_read_complete = &udp_on_read_complete
ioqueue_cb.on_write_complete = &udp_on_write_complete - TCP 전송포트 생성
- TLS 전송포트 생성
- buddy 등록
- 일부 코덱 비활성화 및 우선순위 설정
- 콜 초기화
2. pjsua_app_run 의 오퍼레이션 절차
- pjsip-apps/src/pjsua/pjsua_app.c
- 콘솔 리프레쉬 스레스 생성
- pjsua 시작
- 전화걸기 파리미터 있다면, 콜생성
- 콘솔 대기 및 명령처리 루프
- 어플리케이션 종료.
이 후 이벤트에 따라 함수 호출이 수행된다.
3. 주요 자료구조
아래는 여러함수에서 자주 보게되는 자료구조이다.
- struct pjsua_msg_data
- SIP message와 함께 추가로 보낼 정보를 위한 구조체.
- 멤버: target_uri, content_type(MIME type of message body), msg_body …
- struct pjsua_call
- 어플리케이션 레벨에서 필요한 콜관련 정보(콜시작시간등)
- dlg->mod_data[pjsua.mod.id] 에 저장된다.
- 주요멤버:
pj_time_val:start_time, res_time
pjsip_inv_session:inv,
pjsip_rx_data:*incoming_data,
void:*hold_msg - Outgoing hold tx_data
pjsua_med_tp_state_cb :med_ch_cb - media channel callback.
- struct pjsip_dialog
- 다이얼로그 구조체, 반드시 API를 이용해서 멤버를 변경해야한다.
- 어플리케이션은 잠근 후 바로 읽는 것은 가능하다.
- 잠그는 것은 pjsip_dlg_inc_lock/ xx_dec_lock을 이용해야 한다.
- 멤버 - pjsip_user_agent, pjsip_endpoint, dlg_set, pjsip_module:usage[max_module]
mod_data[max_module], … 등 - struct pjsip_inv
- pjsip/include/pjsip-ua/sip_inv.h
- pool_prov와 pool_active는 re-INVITE 와 UPDATE 에서 임시로 사용된다. pool_prov는 SDP offer나 answer에 사용되고 협상이 끝나면 pool_active처럼 만들어지고, pool_active도 리셋된다.
- 주요멤버:
pj_pool_t *pool - Long term pool
pj_pool_t *pool_pov - Provisional pool,
pjsip_inv_state state - Invite session state
pjsip_dialog *dlg - Underlying dialog
pjsip_role_e role - Invite role: uac/uas
pjmedia_sdp_neg *neg; - Negotiator
pjsip_transaction *invite_tsx; - 1st invite tsx
void *mod_data[PJSIP_MAX_MODULE]; - Modules data.
struct pjsip_timer *timer; - Session Timers
….
4. 전화 수신 절차
주요수행에 따른 흐름은 아래와 같다.
Transport INVITE 수신
mod_pjsua모듈의 on_rx_request(): mod_pjsua_on_rx_request(rdata) 수행시작
*전화 수신을 위한 리소스 설정 후 100 trying전송
- UAS Transaction 생성
Transaction state: NULL -> Trying - Dialog 생성
- Dialog usage:INVITE 세션 생성
- SDP에 따라 미디어 채널 초기화
- 100 Trying 메시지 전송
- 트랜잭션 상태변경 -> 트랜잭션유저:mod_ua 상태변경 -> 다이얼로그 usage 상태변경 -> 어플리케이션 callback함수:on_call_state 수행.
Transaction state: Trying -> Proceeding
Invite Session state:PJSIP_INV_STATE_INCOMING
어플리케이션 callback함수인 on_incoming_call 수행: 링백시작
*INVITE module에서 SDP 협상 및 200 OK를 전송
- pjsua_call_answer2() 수행시작
- SDP 협상 후 결과에 따라 미디어채널 업데이트
- 어플리케이션 callback함수인 on_call_media_state 수행: 링백정지, 컨퍼런스 포트 연결(스트리밍 시작)
- 200 OK 메시지 전송
- 트랜잭션 상태변경 -> 트랜잭션유저:mod_ua 상태변경 -> Dialog usage state -> 어플리케이션 callback함수:on_call_state 수행.
Transaction state: Proceeding -> Complete
Invite Session state: PJSIP_INV_STATE_CONNECTING
call.info: CONNECTING - 트랜젹션 상태변경 후 콜백 수행
- pjsua_call_answer2() 수행완료
mod_pjsua모듈의 on_rx_request(): mod_pjsua_on_rx_reques(rdata) 수행완료
ACK 수신
- ACK 메시지 수신
- User agent module on_rx_request 에서 상태변경 및 Transaction Timer 설정.
Transaction state:Terminated -> Destroyed
Invite Session state: PJSIP_INV_STATE_CONFIRMED
call.info: CONFIRMED - Transaction destroy는 tsx_set_state()에서 등록한 타이머콜백에서 수행된다.
tsx_schedule_timer(.., tsx->timeout_timer, timeout,..)
BYE발신
- BYE메시지 전송
transaction state: NULL -> Trying) - OK 메시지 수신
Tansaction state: Trying -> Complete
Invite Session state: PJSIP_INV_STATE_DISCONNECTED
call.info: DISCONNECTED - Transaction destroy는 왜 없을까?? (Dialog session count가 0인데 Dialog를 소멸시키지 않는 이유는??)
각 모듈에 따른 자세한 흐름은 아래와 같다.
4.1. Application
pjsua_init -> worker_thread -> pjsua_handle_events
- pjsip/src/pjsua-lib/pjsua_core.c
- poll 이벤트 대기 반복
- app_init()에서 pjsua_transport_create() 에서 UDP 패킷 수신시 udp_on_read_complete가 콜백함수로 등록되어 UDP를 수신하면 udp_on_read_complete가 자동으로 호출된다.
4.2. Transport Layer :INVITE 수신
4.2.1. udp_on_read_complete()
- ioqueue로 부터 UDP수신 (recvfrom() 오퍼레이션)이 완료되면 호출된다.
- pjsip_tpmgr_receive_packet(rdata->tp_info.transport->tpmgr, data) 호출
- TCP의 경우 pjsip/src/pjsip/sip_transport_tcp.c : on_data_read() 에서 호출된다.
pjsip_tpmgr_receive_packet()
- pjsip/src/pjsip/sip_transport.c
- mgr->on_rx_msg(mgr->endpt, ..) 호출
4.2.2. pjsip_tpmgr mgr - on_rx_msg()
- pjsip/src/pjsip/sip_endpoint.c
- mgr->on_rx_msg = endpt_on_rx_msg 함수 진입
128 15:04:38.901 sip_endpoint.c Processing incoming message: Request msg INVITE/cseq=20 (rdata0xb5a0047c)
|
- Endpoint Distribution 시작 : pjsip_endpt_process_rx_data() - 우선순위에 따라 각 모듈의 on_rx_request() 콜백을 호출한다. 모듈 호출순서:
mod-pjsua-log -> mod-msg-print -> mod-tsx-layer -> mod-ua -> mod-100rel -> mod-invite -> mod-evsub
-> mod-presence -> mod-mwi -> mod-refer -> mod-stateful-util -> mod-pjsuaz
mod_tsx_layer에 transaction도 없고, mod_ua에 Dialog도 없어 최상위 모듈까지 전달된다. - endpt_on_rx_msg 함수 완료
4.3. mod-pjsua-log
4.3.1. pjsip_moudle pjsua_msg_logger - on_rx_request()
- /pjsip/src/pjsua-lib/pjsua_core.c
- logging_on_rx_msg 함수진입 메시지 내용 출력
129 15:04:38.901 pjsua_core.c .RX 1188 bytes Request msg INVITE/cseq=20 (rdata0xb5a0047c) from UDP 192.168 .1.17:5060:
130 INVITE sip:1234@192.168.1.11:5060;ob SIP/2.0
131 Record-Route: <sip:192.168.1.17;lr>
….
|
- logging_on_rx_msg 함수완료
4.4. mod-pjsua
4.4.1. pjsip_modlue mod_initializer[mod-pjsua] - on_rx_request()
- INVITE 요청을 받아 SDP를 협상하고, 협상된 SDP에 따라 미디어를 설정한 후 OK 메시지를 전송한다.
- pjsip/src/pjsua-lib/pjsua_core.c
- mod_pjsua_on_rx_request호출 INVITE_METHOD일 경우만 pjsua_call_on_incoming 함수진입
- 다이얼로그생성 :
- pjsip_dlg_create_uas_and_inc_lock() 함수진입
- UAS transaction 생성:pjsip_tsx_create_uas()
- user agent를 다이얼로그에 등록
20:09:33.842 dlg0xb5a05364 ..UAS dialog created
|
- pjsip_dlg_create_uas_and_inc_lock() 함수완료
- 인증서 설정
- INVITE 세션생성
- pjsip_inv_create_uas() 함수진입
- mod_invite를 dialog usage로 등록
- UAS invite session 생성
- pjsip_inv_create_uas() 함수완료
- 미디어 채널 초기화
- pjsua_media_channel_init() 함수진입
- SDP가 없을 경우 pjsua_call_answer()에서 처리된다.
- RTCP, RTP 소켓 생성 및 네트워크전송 준비 :create_udp_media_transport()
- 통화를 위한 미디어 인덱스 선택
- pjsua_media_channel_init() 함수완료
- 세션 타이머 초기화
- INVITE에 대한 초기응답 메시지 전송(100 trying)
- 메시지생성:pjsip_inv_initial_answer(100) 호출
- 메시지전송:pjsip_inv_send_msg(100) 호출
- app_int()에서 등록된 app_config.cfg.cb.on_incoming_call() 호출.
- pjsua_call_on_incoming 함수완료
4.5. Application
4.5.1. app_config.cfg.cb.on_incoming_call()
- pjsip-apps/src/pjsua/pjsua_app.c
- on_incoming_call() 함수진입
- 링백시작
- 자동응답의 경우 INVITE 요청에 대한 응답을 처리한다.
- 자동응답인 경우 pjsua_call_answer2() 호출. 아니면 함수완료 후 ui_answer_call()에서 호출됨.
- pjsua_call_answer2() 함수진입
- pjsip/src/pjsua-lib/pjsua_call.c
- 다이얼로그 뮤텍스 잠그고 세션카운트를 증가시킨다.
- 수신된 콜에 SDP offer가 없다면, 미디어 채널이 초기화 되지않은 경우이므로 미디어 채널을 초기화 한다.
- pjsua_media_channel_init() 함수 수행,
- INVITE에 대한 응답 메시지 전송(200 Trying)
- 메시지생성:pjsip_inv_answer(200) 호출
- 메시지전송:pjsip_inv_send_msg(200)호출
- pjsua_call_answer2() 함수완료
- on_incoming_call() 함수완료
180 Rining 를 UAC에 전달 후 pjsua가 a를 누른 상태, UAS가 200 OK로 응답하고 미디어가 연결되는 과정이다.
ui_answer_call() 함수진입
- current_call 은 전역변수로 전화요청받은 콜 아이디가 세팅되어 있다.
- call_opt 는 전역변수로 현재 통화의 옵션이 세팅되어 있다.
- 사용자로 부터 상태코드 입력 (예: 200)
- 메시지를 담을 구조체 pjsua_msg_data 조기화
- pjsua_call_answer2() 호출: 자동응답의 경우 app_config.cfg.cb. on_incoming_call()에서 호출됨.
:pjsip_inv_answer(200) 호출,
pjsip_inv_send_msg(200)호출.
ui_answer_call() 함수완료
4.6. mod-invite
4.6.1. pjsip_inv_answer(): OK 생성
- INVITE 요청을 처리한다.
- pjsip/src/pjsip-ua/sip_inv.c
- process_answer() 함수진입
- pjsip/src/pjsip-ua/sip_inv.c
- INVITE 응답과 re-INVITE의 초기화 및 subsequent를 처리한다.
- SDP negotiator가 준비됐으면, 협상을 시작한다.
- inv_negotiate_sdp() 호출.
- process_answer() 함수완료
- 응답메시지에 세션 타임아웃을 설정한다. : pjsip_timer_update_resp()
- 지원하지 않는 기능을 헤더에서 제거한다.: cleanup_allow_sup_hdr()
4.6.1.1. inv_negotiate_sdp()
- SDP 협상을 수행하고 협상정보에 따라 INVITE session의 미디어를 업데이트한다.
- pjmedia_sdp_neg_negotiate()
- mod_inv.cb.on_media_update() 호출
4.6.1.2. inv_cb.on_media_update()
pjsua_call_on_media_update() 함수진입
- SDP 협상이 완료되면 이 INVITE 콜백함수가 호출됨. 이 함수에서 미디어를 시작하거나 업데이트한다.
- pjsip/src/pjsua-lib/pjsua_call.c
- 협상된 SPD에 따라 미디어 설정: pjsua_media_channel_update()
- pjsua_media_channel_update() 함수진입
- SDP에 따라 stream 설정: pjmedia_stream_info_from_sdp()
- pjmedia_transport_media_start() : Do nothing.
- pjsua_aud_channel_update() : Encoder / Decoder 스트림 생성 후 컨퍼런스에 추가.
- pjsua_media_channel_update() 함수완료
- app_config.cfg.cb.on_call_media_state() 호출
pjsua_call_on_media_update() 함수완료
app_config.cfg.cb.on_call_media_state()
- 미디어 상태 변경에 따라 이 콜백함수가 호출됨.
- call_info의 미디어 타입에 따라 on_call_audio_state(), on_call_video_state() 호출
4.6.1.3. on_call_audio_state()
- pjsip-apps/src/pjsua/pjsua_app.c
- 링백 전달 정지.
- 옵션에 따라 Loopback포트 연결
- 옵션에 따라 레코딩포트 연결
- 옵션에 따라 파일플레이백포트 연결
- pjsua_conf_connect() 함수진입
- pjsip/src/pjsua-lib/pjsua_aud.c
- 사운드 디바이스의 idle timer가 활성화된 경우, 비활성화설정.
- playback & capure를 위한 장치 설정: pjsua_set_snd_dev() - 오디오장치 오픈 및 스레드시작.
- pjmedia_conf_connect_port() : 연결포트 세팅.
- pjsua_conf_connect() 함수완료
4.6.2. pjsip_inv_send_msg():OK 전송
- pjsua_call_answer2()에서 pjsip_inv_answer()수행 후 호출된다.
- 요청/응잡 메시지를 전달하고 트랜잭션레이어에서 어플리케이션레이어까지 상태변경을 통지한다.(각 모듈의 콜백함수를 호출함으로써 수행된다.)
- pjsip/src/pjsip-ua/sip_inv.c
- 디버깅메시지:
inv0xb5a05364 ...Sending Response msg 100/INVITE/cseq=20 (tdta0xb5a0f040)
|
- 응답의 경우:pjsip_dlg_send_response()호출, 요청의 경우: pjsip_dlg_send_request()을 호출한다.
100 trying 또는 200 OK는 응답이므로 pjsip_dlg_send_response()가 호출된다. - pjsip_dlg_send_response() 호출
4.6.2.1. pjsip_dlg_send_response()
- statefully 응답을 전달한다.
- pjsip/src/pjsip/sip_dialog.c
- 디버깅메시지
dlg0xb5a05364 ....Sending Response msg 100/INVITE/cseq=20 (tdta0xb5a0f040)
|
- pjsip_tsx_send_msg() 함수진입 : 트랜잭션에 응답메시지 전송을 요청한다.
- 이 함수는 메시지를 전송하기위해 트랜잭션 유저에 의해 호출된다.
- src/pjsip/sip_transaction.c
- 디버깅메시지:
tsx0xb5a05d74 ....Sending Response msg 100/INVITE/cseq=20 (tdta0xb5a0f040) in state Trying
|
- 트랜잭션에 transport 셀렉터 설정: pjsip_tx_data_set_transport
- 트랜잭션의 state handler 호출: INVITE 메시지 수신시 tsx_set_state()에서 tsx_state_handler_uas[trying]로 설정되어있다.
- tsx_on_state_trying() 함수진입
- 요청메시지를 받았으나 응답을 보내지 않은 상태의 UAS일 경우 Trying state이다.
- 이 함수는 trying 메시지를 전송하고 트랜잭션상태를 PJSIP_TSX_STATE_PROCEEDING로 변경한다.
이 상태변경은 어플리케이션 레벨까지 상위 모듈에 전달된다. - 메시지 전송: tsx_on_state_proceeding_uas() -> tsx_send_msg() -> pjsip_transport_send()
- 상태변경 및 변경통지:
tsx_set_state(PJSIP_TSX_STATE_PROCEEDING) : Transaction State 변경.
-> (*tsx->tsx_user->on_tsx_state)(tsx, &e) : tsx_user는 mod_ua이다.
-> struct user_agent mod_ua->on_tsx_state() -> mod_ua_on_tsx_state()
-> pjsip_dlg_on_tsx_state() : dialog usage modlue에 전달한다.
-> struct mod_inv->on_tsx_state() -> mod_inv_on_tsx_state()
-> (*inv_state_handler[inv->state])(inv, e) -> inv_on_state_null()
-> inv_set_state(PJSIP_INV_STATE_INCOMING): Invite Session state 변경 - mod_inv_on_tsx_state()에서 inv_state_handler() 수행 후 mod_inv.cb.on_tsx_state_changed()수행:
pjsua_var.ua_cfg.cb.on_call_tsx_state():on_call_tsx_state() 수행
메시지가 REFER, MESSAGE 일 경우 추가수행 - tsx_on_state_trying() 함수완료
- pjsip_tsx_send_msg() 함수완료
4.6.2.2. inv_set_state()
- pjsip/src/pjsip-ua/sip_inv.c
- session state를 변경한다. : inv->state = state
- mod_inv.cb.on_state_changed() -> pjsua_call_on_state_changed()
- pjsua_call_on_state_changed() 함수진입
- pjsip/src/pjsua-lib/pjsua_call.c
- 이 콜백은 invite session으로 부터 session state가 변경되면 호출된다.
- pjsua_var.ua_cfg.cb.on_call_state() 호출
- pjsua_call_on_state_changed() 함수완료
app_config.cfg.cb.on_call_state()
- invite state 변경시 이 콜백함수가 호출된다.
on_call_state() 함수진입
- call_info 생성: call_info->state = call->inv->state
- call_info 의 전화가 끊어진 경우 링백정지: ring_stop()
- 파일재생의 경우, 재생위치 Rewind.
- Duration이 있다면, 전화종료.
- current_call = call_id
on_call_state() 함수완료
4.7. Transport Layer: ACK 수신
udp_on_read_complete() -> pjsip_tpmgr_receive_packet() -> pjsip_tpmgr mgr - on_rx_msg() 호출
- pjsip/src/pjsip/sip_endpoint.c
- mgr->on_rx_msg = endpt_on_rx_msg 함수 진입
- 디버깅 메시지:
16:21:16.176 sip_endpoint.c @Processing incoming message: Request msg ACK/cseq=20 (rdata0xb5a0047c)
|
- Endpoint Distribution 시작 : pjsip_endpt_process_rx_data() - 우선순위에 따라 각 모듈의 on_rx_request() 콜백을 호출한다. 모듈 호출순서:
mod-pjsua-log -> mod-msg-print -> mod-tsx-layer -> mod-ua
mod-ua에 invite session을 가지 Dialog가 존재하므로 mod-ua->on_rx_reuqest()는 PJ_TRUE를 리턴한다. - endpt_on_rx_msg 함수 완료
4.7.1. mod-pjsua-log
pjsip_moudle pjsua_msg_logger - on_rx_request() 호출
- /pjsip/src/pjsua-lib/pjsua_core.c
- logging_on_rx_msg 함수진입 메시지 내용 출력
382 16:21:16.176 pjsua_core.c .RX 434 bytes Request msg ACK/cseq=20 (rdata0xb5a0047c) from UDP 192.168.1.1 7:5060:
383 ACK sip:1234@192.168.1.11:5060;ob SIP/2.0
384 Via: SIP/2.0/UDP 192.168.1.17:5060;branch=z9hG4bK1677.d27d82c2.2
385 Via: SIP/2.0/UDP 192.168.1.26:5060;received=192.168.1.26;rport=5060;branch=z9hG4bK.LPfi39mfK
386 From: "alice" <sip:6983@192.168.1.17>;tag=wXVZb-3v-
387 To: <sip:1234@192.168.1.17>;tag=ded5c253-61ef-4fd9-8d40-726a57fb8721
….
|
- logging_on_rx_msg 함수완료
4.7.2. mod-ua
pjsip_moudle -m on_rx_request() 호출
mod_ua_on_rx_request() 함수진입
- Dialog set에서 Dialog 검색. Dialog가 발견되지 않으면 UAS가 NOTIFY를 SUBSCRIBE전에 보낸 경우임.
- 다이얼로그에 메시지 전달: pjsip_dlg_on_rx_request()
- pjsip_dlg_on_rx_request() 함수진입
- 트랜젹션이 없을 경우, 트랜잭션 생성: pjsip_tsx_create_uas()
- 다이얼로그 생성(??)
- *dlg->usage[i]->on_rx_request : mod_inv_on_rx_request() 호출
- mod_inv_on_rx_request() 함수진입
- invite sesstion state가 DISCONNECTED가 아닐 때 필요한 ACK request의 SDP 처리 : inv_check_sdp_in_incoming_msg()
- Invite transaction 종료:pjsip_tsx_terminate()
- transaction state 변경:
tsx_set_state(Terminated) 함수진입
tsx->tsx_user->on_rx_response)(rdata)
tsx->tsx_user->on_tsx_state()
tsx_cancel_timer(tsx->timeout_timer)
tsx_schedule_timer(tsx->timeout_timer)
tsx_set_state(Terminated) 함수완료
tsx->tsx_user->on_tsx_state:mod_ua_on_tsx_state() -> pjsip_dlg_on_tsx_state() -> dlg->usage[i]->on_tsx_state:mod_inv_on_tsx_state() -> pjsua_call_on_tsx_state_changed() -> on_call_tsx_state()
mod_inv_on_rx_request() 함수완료 - pjsip_dlg_on_rx_request() 함수완료
mod_ua_on_rx_request() 함수완료
4.7.3. Transaction Timer
tsx_set_state에서 등록된 스케쥴 타이머가 시간만료로 콜백함수가 호출된다.
- transaction 생성시 callback함수 등록:
tsx_create() :: tsx->timeout_timer.cb = &tsx_timer_callback;
tsx->retransmit_timer.cb = &tsx_timer_callback;
pj_grp_lock_add_handler(tsx->grp_lock,...., &tsx_on_destroy); - 타임아웃 등록
mod_ua_on_rx_request() -> tsx_set_state() :tsx_cancel_timer(), tsx_schedule_timer() - 이벤트에 따른 콜백함수 호출:
pjsip_endpt_handle_events2() -> pj_timer_heap_poll 함수진입
타임아웃이 발생되면 (*node->cb)(ht, node) : tsx_timer_callback() 이 호출됨.
pj_grp_lock_dec_ref(grp_lock) : Lock 레퍼런스 카운터가 0이면 tsx_on_destroy()호출 -> Transaction 소멸.
pj_timer_heap_poll 함수완료
댓글 없음:
댓글 쓰기