Ejemplo n.º 1
0
int call_answer(struct call *call, uint16_t scode)
{
	struct mbuf *desc;
	int err;

	if (!call || !call->sess)
		return EINVAL;

	if (STATE_INCOMING != call->state) {
		return 0;
	}

	info("answering call from %s with %u\n", call->peer_uri, scode);

	if (call->got_offer) {

		err = update_media(call);
		if (err)
			return err;
	}

	err = sdp_encode(&desc, call->sdp, !call->got_offer);
	if (err)
		return err;

	err = sipsess_answer(call->sess, scode, "Answering", desc,
			     "Allow: %s\r\n", uag_allowed_methods());

	mem_deref(desc);

	return err;
}
Ejemplo n.º 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;

   }

}