int call_hangup(struct call *call, uint16_t scode, const char *reason) { int err = 0; if (!call) return EINVAL; switch (call->state) { case STATE_INCOMING: if (scode < 400) { scode = 486; reason = "Rejected"; } info("call: rejecting incoming call from %s (%u %s)\n", call->peer_uri, scode, reason); (void)sipsess_reject(call->sess, scode, reason, NULL); break; default: info("call: terminate call '%s' with %s\n", sip_dialog_callid(sipsess_dialog(call->sess)), call->peer_uri); call->sess = mem_deref(call->sess); break; } set_state(call, STATE_TERMINATED); call_stream_stop(call); return err; }
void tcsipcall_control(struct tcsipcall*call, int action) { int err; struct mbuf *mb = NULL; /* * XXX: drop bytes when confirmation received * */ switch(action) { case CALL_ACCEPT: if(call->cstate & (CSTATE_ERR|CSTATE_EST)) return; if(call->cdir != CALL_IN) return; if(! (call->cstate & CSTATE_ICE)) { DROP(call->cstate, CSTATE_RING); return; } // 200 err = tcmedia_offer(call->media, call->msg->mb, &mb); if(err) { DROP(call->cstate, CSTATE_RING); err |= CSTATE_ERR; break; } /* * Workarround * * libre uses msg->dst to fill in Contact header * value. * This works well for UDP where one socket used * for both send and recieve, but no for TCP * TCP transport uses one socket for listen * and other to connect to registar. * Address msg->dst is the recieving part * of upstream socket UAC->REGISTAR * and cannot be used to connect from outside * * */ sa_set_port((struct sa*)&call->msg->dst, sa_port(&call->uac->laddr)); sipsess_answer(call->sess, 200, "OK", mb, NULL); mem_deref(mb); DROP(call->cstate, CSTATE_RING); call->cstate |= CSTATE_EST; break; case CALL_REJECT: case CALL_BYE: if( TEST(call->cstate, CSTATE_IN_RING) ) { sipsess_reject(call->sess, 486, "Reject", NULL); DROP(call->cstate, CSTATE_IN_RING); call->reason = CEND_HANG; } if( TEST(call->cstate, CSTATE_EST) ) { // bye sent automatically in deref DROP(call->cstate, CSTATE_EST); call->reason = CEND_OK; } if( TEST(call->cstate, CSTATE_OUT_RING ) ) { // cancel DROP(call->cstate, CSTATE_EST); call->reason = CEND_CANCEL; } tcsipcall_hangup(call); break; } }