Beispiel #1
0
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;
}
Beispiel #2
0
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;

   }

}