emiago/sipgo

Server OnCancel function is not called when receive CANCEL request

mlcoor opened this issue · 4 comments

Hi,emiage.

I have a issue about server request handler.

I use func (srv *sipgo.Server) OnCancel(handler sipgo.RequestHandler) registers Cancel request handler name onCancel. when caller send INVITE to callee and send CANCEL to callee after a few second, the onCancel function did not be called. caller and callee both are linPhone app.

I local the code where the onCancel function should be call.

func (txl *TransactionLayer) handleRequest(req *Request) {
	key, err := MakeServerTxKey(req)
	if err != nil {
		txl.log.Error().Err(err).Msg("Server tx make key failed")
		return
	}

	tx, exists := txl.getServerTx(key)
	if exists {
		if err := tx.Receive(req); err != nil {
			txl.log.Error().Err(err).Msg("Server tx failed to receive req")
		}
		return
	}

	if req.IsCancel() {
		// transaction for CANCEL already completed and terminated
		return
	}

	// Connection must exist by transport layer.
	// TODO: What if we are gettinb BYE and client closed connection
	conn, err := txl.tpl.GetConnection(req.Transport(), req.Source())
	if err != nil {
		txl.log.Error().Err(err).Msg("Server tx get connection failed")
		return
	}

	tx = NewServerTx(key, req, conn, txl.log)

	if err := tx.Init(); err != nil {
		txl.log.Error().Err(err).Msg("Server tx init failed")
		return
	}
	// put tx to store, to match retransmitting requests later
	txl.serverTransactions.put(tx.Key(), tx)
	tx.OnTerminate(txl.serverTxTerminate)

	txl.reqHandler(req, tx)
}

onCancel should be call by txl.reqHandler(req, tx), but when request method is CANCEL, handleRequest go into:

if exists {
    if err := tx.Receive(req); err != nil {
        txl.log.Error().Err(err).Msg("Server tx failed to receive req")
    }
    return
}

handleRequest return before call onCancel. the problem may be caused by MakeServerTxKey, it make the same key as INVITE if request method is ACK or CANCEL, but ACK dot not has this problem.

Any help is appreciated.Thanks.

you have tx.Cancel() channel. This is transaction cancel, so normally in case of Invite you need to handle. If you are building dialogs, use DialogServer and report if there are some issues

Thank you, I know now that I can use tx.Cancel(). But I still don't understand why onCancel is not called, which makes the behavior upon receiving a CANCEL request different from other requests. Is it intentionally designed this way?

hi @mlcoor I see what you mean. On non existing transaction response should be generated as well.
Thanks for reporting.
So question is also, what is your use case to have this propagated. Generating non 2xx response?

I try to notify another user that the current user's call has ended when receiving the CANCEL request.If the transaction doesn't exist, the onCancel function will be called as expected.
But now that I can use tx.Cancel().It seems like this issue has been resolved.
thanks.