I use Jain Sip to create a sip app. It can send/receive INVITE/ ACK/ BYE, and send back the response with SDP if necessary. But when it receives BYE from the other side, a 481 will be thrown by Jain Sip. I tried to figure out what happen for a week and still don't understand.
I send response statefully by using ServerTransaction.sendResponse from incoming request. Automatic Dialog is on.
here is the whole source code (I use swing for the interface)
public class SipClient extends JFrame implements SipListener {
SipFactory sipFactory; // used to access the SIP API
SipStack sipStack;
SipProvider sipProvider; // used to send SIP messages
MessageFactory messageFactory; // used to create SIP message factory
HeaderFactory headerFactory; // used to create SIP headers
AddressFactory addressFactory; // used to create SIP URIs
ListeningPoint listeningPoint; // SIP listening IP address & port
Properties properties;
// local configuration
String ip; // locap IP address
int port = 5060; // local port
String protocol = "udp"; // local protocol
int tag = (new Random().nextInt()); // local tag
Address contactAddress;
ContactHeader contactHeader;
public static final boolean callerSendsBye = true;
private Dialog dialog;
private ServerTransaction servTransaction;
private ClientTransaction cliTransaction;
private long cseq = 1L;
private Request inviteRequest;
private Request ackRequest;
/**
* Creates new form SipClient
*/
public SipClient() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed"
// desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {}
private void onOpen(java.awt.event.WindowEvent evt) {
// A method called when you open the application
try {
// get the local IP address
this.ip = "127.0.0.12";
// create the SIP factory and set the path name
this.sipFactory = SipFactory.getInstance();
this.sipFactory.setPathName("gov.nist");
// create and set the SIP stack properties
this.properties = new Properties();
this.properties.setProperty("javax.sip.STACK_NAME", "stack");
this.properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "on");
// create the SIP stack
this.sipStack = this.sipFactory.createSipStack(this.properties);
// create the SIP message factory
this.messageFactory = this.sipFactory.createMessageFactory();
// create the SIP header factory
this.headerFactory = this.sipFactory.createHeaderFactory();
// create the SIP address factory
this.addressFactory = this.sipFactory.createAddressFactory();
// create the SIP listening point and bind it to the local IP
// address, port & protocol
this.listeningPoint = this.sipStack.createListeningPoint(this.ip,
this.port, this.protocol);
// create the SIP provider
this.sipProvider = this.sipStack.createSipProvider(listeningPoint);
// add application as sip listener
this.sipProvider.addSipListener(this);
// create contact address used for all SIP messages
this.contactAddress = this.addressFactory.createAddress("sip:"
+ this.ip + ":" + this.port);
// create contact header used for all SIP messages
this.contactHeader = this.headerFactory
.createContactHeader(contactAddress);
// display local IP address and port in text area
this.textArea.append("Local address:" + this.ip + ":" + this.port
+ "\n Tag:" + this.tag + "\n");
}
catch (Exception e) {
// if error occurs, display an error message box and exit
JOptionPane.showMessageDialog(this, e.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
System.exit(-1);
}
}
private void onRegisterStateless(java.awt.event.ActionEvent evt) {
// A method called when you click on the "Reg (SL)" button
try {
// Get the destination address from the text field
Address addressTo = this.addressFactory
.createAddress(this.textField.getText());
// Create the request URI for the SIP message
javax.sip.address.URI requestURI = addressTo.getURI();
// Create the SIP message headers
// The " Via " headers
ArrayList viaHeaders = new ArrayList();
ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip,
this.port, "udp", null);
viaHeaders.add(viaHeader);
// The " Max - Forwards " header
MaxForwardsHeader maxForwardsHeader = this.headerFactory
.createMaxForwardsHeader(70);
// The " Call - Id " header
CallIdHeader callIdHeader = this.sipProvider.getNewCallId();
// The " CSeq " header
CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(1L,
Request.REGISTER);
// The " From " header
FromHeader fromHeader = this.headerFactory.createFromHeader(
this.contactAddress, String.valueOf(this.tag));
// The " To " header
ToHeader toHeader = this.headerFactory.createToHeader(addressTo,
null);
// Create the REGISTER request
Request request = this.messageFactory.createRequest(requestURI,
Request.REGISTER, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwardsHeader);
// Add the " Contact " header to the request .
request.addHeader(contactHeader);
// Send the request statelessly through the SIP provider .
this.sipProvider.sendRequest(request);
// Display the message in the text area .
this.textArea.append("Request sent :\n " + request.toString()
+ "\n\n");
}
catch (Exception e) {
// If an error occurred , display the error .
this.textArea.append("Request sent failed : " + e.getMessage()
+ "\n");
}
}
private void onRegisterStatefull(java.awt.event.ActionEvent evt) {
// A method called when you click on the "Reg (SF)" button
try {
// Get the destination address from the text field
Address addressTo = this.addressFactory
.createAddress(this.textField.getText());
// Create the request URI for the SIP message
javax.sip.address.URI requestURI = addressTo.getURI();
// Create the SIP message headers
// The " Via " headers
ArrayList viaHeaders = new ArrayList();
ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip,
this.port, "udp", null);
viaHeaders.add(viaHeader);
// The " Max - Forwards " header
MaxForwardsHeader maxForwardsHeader = this.headerFactory
.createMaxForwardsHeader(70);
// The " Call - Id " header
CallIdHeader callIdHeader = this.sipProvider.getNewCallId();
// The " CSeq " header
CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(1L,
Request.REGISTER);
// The " From " header
FromHeader fromHeader = this.headerFactory.createFromHeader(
this.contactAddress, String.valueOf(this.tag));
// The " To " header
ToHeader toHeader = this.headerFactory.createToHeader(addressTo,
null);
// Create the REGISTER request
Request request = this.messageFactory.createRequest(requestURI,
Request.REGISTER, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwardsHeader);
// Add the " Contact " header to the request .
request.addHeader(contactHeader);
// Send the request statelessly through the SIP provider .
// this.sipProvider.sendRequest(request);
// create new SIP client transaction
ClientTransaction transaction = this.sipProvider
.getNewClientTransaction(request);
// send the request statefully, through the client transaction
transaction.sendRequest();
// Display the message in the text area .
this.textArea.append("Request sent :\n " + request.toString()
+ "\n\n");
}
catch (Exception e) {
// If an error occurred , display the error .
this.textArea.append("Request sent failed : " + e.getMessage()
+ "\n");
}
}
private void onInvite(java.awt.event.ActionEvent evt) {
// A method called when you click on the "Invite" button.
try {
// Get the destination address from the text field
Address addressTo = this.addressFactory
.createAddress(this.textField.getText());
// Create the request URI for the SIP message
javax.sip.address.URI requestURI = addressTo.getURI();
// Create the SIP message headers
// The " Via " headers
ArrayList viaHeaders = new ArrayList();
ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip,
this.port, "udp", null);
viaHeaders.add(viaHeader);
// The " Max - Forwards " header
MaxForwardsHeader maxForwardsHeader = this.headerFactory
.createMaxForwardsHeader(70);
// The " Call - Id " header
CallIdHeader callIdHeader = this.sipProvider.getNewCallId();
// The " CSeq " header
CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(cseq,
Request.INVITE);
cseq++;
// The " From " header
FromHeader fromHeader = this.headerFactory.createFromHeader(
this.contactAddress, String.valueOf(this.tag));
// The " To " header
ToHeader toHeader = this.headerFactory.createToHeader(addressTo,
null);
// Create the REGISTER request
Request request = this.messageFactory.createRequest(requestURI,
Request.INVITE, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwardsHeader);
// Add the " Contact " header to the request .
request.addHeader(contactHeader);
// create new SIP client transaction
cliTransaction = this.sipProvider.getNewClientTransaction(request);
// send the request statefully, through the client transaction
cliTransaction.sendRequest();
dialog = cliTransaction.getDialog();
// Display the message in the text area .
this.textArea.append("Request sent :\n " + request.toString()
+ "\n");
}
catch (Exception e) {
// If an error occurred , display the error .
this.textArea.append("Request sent failed : " + e.getMessage()
+ "\n");
}
}
private void onBye(java.awt.event.ActionEvent evt) {
// A method called when you click on the "Bye" button.
try {
Request byeRequest = dialog.createRequest(Request.BYE);
cliTransaction = sipProvider
.getNewClientTransaction(byeRequest);
dialog.sendRequest(cliTransaction);
this.textArea.append("Request sent :\n " + byeRequest.toString()
+ "\n");
} catch (Exception e) {
// If an error occurred , display the error .
this.textArea.append("Request sent failed : " + e.getMessage()
+ "\n");
}
}
/**
* @param args
* the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
// <editor-fold defaultstate="collapsed"
// desc=" Look and feel setting code (optional) ">
/*
* If Nimbus (introduced in Java SE 6) is not available, stay with the
* default look and feel. For details see
* http://download.oracle.com/javase
* /tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager
.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(SipClient.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(SipClient.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(SipClient.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(SipClient.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
}
// </editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new SipClient().setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton buttonBye;
private javax.swing.JButton buttonInvite;
private javax.swing.JButton buttonRegisterStatefull;
private javax.swing.JButton buttonRegisterStateless;
private javax.swing.JScrollPane scrollPane;
private javax.swing.JTextArea textArea;
private javax.swing.JTextField textField;
// End of variables declaration//GEN-END:variables
@Override
public void processRequest(RequestEvent requestEvent) {
// A method called when you receive a SIP request
// Get the request.
Request request = requestEvent.getRequest();
sipProvider = (SipProvider) requestEvent.getSource();
this.textArea.append("\nRECEIVED " + request.getMethod() + " "
+ request.getRequestURI().toString());
try {
// Get or create the server transaction.
servTransaction = requestEvent.getServerTransaction();
if (null == servTransaction) {
servTransaction = this.sipProvider
.getNewServerTransaction(request);
}
// Process the request and send a response.
if (request.getMethod().equals(Request.INVITE)) {
// If the request is an INVITE.
processInvite(request, servTransaction);
} else if (request.getMethod().equals(Request.ACK)) {
// If the request is an ACK.
this.textArea.append("\n RECEIVED : " + request.getMethod());
} else if (request.getMethod().equals(Request.BYE)) {
// If the request is a BYE.
processBye(request, servTransaction);
} else if (request.getMethod().equals(Request.CANCEL)) {
processCancel(request, servTransaction);
}
} catch (SipException e) {
this.textArea.append("\nERROR (SIP): " + e.getMessage());
} catch (Exception e) {
this.textArea.append("\nERROR: " + e.getMessage());
}
}
@Override
public void processResponse(ResponseEvent responseEvent) {
// A method called when you receive a SIP request.
// Get the response .
// Get or create the server transaction.
Response response = responseEvent.getResponse();
int status = response.getStatusCode();
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
switch (status) {
case Response.TRYING: // trying
try {
this.textArea.append("\n RECEIVED RESPONSE : " + status
+ response.toString());
} catch (Exception e) {
this.textArea.append("\n ERROR: " + e.getMessage());
}
break;
case Response.RINGING: // ringing
try {
this.textArea.append("\n RECEIVED RESPONSE : " + status
+ response.toString());
} catch (Exception e) {
this.textArea.append("\n ERROR: " + e.getMessage());
}
break;
case Response.OK: // OK
this.textArea.append("\n RECEIVED RESPONSE : " + status
+ response.toString());
if (cseq.getMethod().equals(Request.INVITE)) {
try {
ackRequest = dialog.createAck(((CSeqHeader) response
.getHeader(CSeqHeader.NAME)).getSeqNumber());
dialog.sendAck(ackRequest);
this.textArea.append("\n Request sent :\n "
+ ackRequest.toString() + "\n");
} catch (Exception e) {
this.textArea.append("\n ERROR: " + e.getMessage());
}
}
break;
default:
break;
}
}
@Override
public void processTimeout(TimeoutEvent timeoutEvent) {
// A method called when a SIP operation times out.
this.textArea.append(" \n Transaction Time out");
}
@Override
public void processIOException(IOExceptionEvent exceptionEvent) {
// A method called when a SIP operation results in an I/O error.
this.textArea.append("\n IOException happened for "
+ exceptionEvent.getHost() + " port = "
+ exceptionEvent.getPort());
}
@Override
public void processTransactionTerminated(
TransactionTerminatedEvent transactionTerminatedEvent) {
// A method called when a SIP transaction terminates.
this.textArea.append("\n Transaction terminated event received");
}
@Override
public void processDialogTerminated(
DialogTerminatedEvent dialogTerminatedEvent) {
// A method called when a SIP dialog terminates.
this.textArea.append("\n Dialog Terminated event received");
}
/**
* Process the invite request.
*/
public void processInvite(Request request,
ServerTransaction serverTransaction) {
try {
this.textArea.append("\n" + request.toString()
+ "\n sending TRYING & RINGING");
// trying
Response tryResponse = messageFactory.createResponse(
Response.TRYING, request);
serverTransaction.sendResponse(tryResponse);
this.textArea.append("\n SENT " + tryResponse.getStatusCode() + " "
+ tryResponse.getReasonPhrase());
// ringing
Response ringResponse = messageFactory.createResponse(
Response.RINGING, request);
serverTransaction.sendResponse(ringResponse);
this.textArea.append("\n SENT " + ringResponse.getStatusCode()
+ " " + ringResponse.getReasonPhrase());
Response okResponse = messageFactory.createResponse(Response.OK,
request);
((ToHeader) okResponse.getHeader("To")).setTag(String
.valueOf(this.tag));
okResponse.addHeader(this.contactHeader);
serverTransaction.sendResponse(okResponse);
this.textArea.append("\n SENT " + okResponse.getStatusCode() + " "
+ okResponse.getReasonPhrase());
this.textArea.append("\n"+okResponse.toString());
} catch (Exception e) {
this.textArea.append("\n ERROR: " + e.getMessage());
}
}
public void processBye(Request request, ServerTransaction serverTransaction) {
try {
this.textArea.append("\n" + request.toString());
if (serverTransaction == null) {
this.textArea.append("\n null transaction");
return;
}
Response response = messageFactory.createResponse(Response.OK,
request);
serverTransaction.sendResponse(response);
} catch (Exception e) {
this.textArea.append("\n ERROR: " + e.getMessage());
}
}
public void processCancel(Request request,
ServerTransaction serverTransaction) {
try {
if (serverTransaction == null) {
this.textArea.append("null ServerTransaction");
return;
}
this.textArea.append("Received a Cancel sending OK");
Response response = messageFactory.createResponse(Response.OK,
request);
serverTransaction.sendResponse(response);
if (dialog.getState() != DialogState.CONFIRMED) {
response = messageFactory.createResponse(
Response.REQUEST_TERMINATED, inviteRequest);
serverTransaction.sendResponse(response);
}
} catch (Exception e) {
this.textArea.append("\n ERROR: " + e.getMessage());
}
}
here the log (the bye sent by client is not received and the client received 481 Call leg/Transaction does not exist)
LOG
<!-- Use the Trace Viewer in src/tools/tracesviewer to view this trace
Here are the stack configuration properties
javax.sip.IP_ADDRESS= null
javax.sip.STACK_NAME= stack
javax.sip.ROUTER_PATH= null
javax.sip.OUTBOUND_PROXY= null
-->
<description
logDescription="stack"
name="stack"
auxInfo="null"/>
<message
from="127.0.0.12:5060"
to="127.0.0.11:5060"
time="1437463865920"
isSender="true"
transactionId="z9hg4bk-393131-d6f070870ff38a7bc7a5764e8e3f6d3b"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="INVITE sip:alice@127.0.0.11:5060 SIP/2.0"
>
<![CDATA[INVITE sip:alice@127.0.0.11:5060 SIP/2.0
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
CSeq: 1 INVITE
From: <sip:127.0.0.12:5060>;tag=2074886745
To: <sip:alice@127.0.0.11:5060>
Via: SIP/2.0/UDP 127.0.0.12:5060;branch=z9hG4bK-393131-d6f070870ff38a7bc7a5764e8e3f6d3b
Max-Forwards: 70
Contact: <sip:127.0.0.12:5060>
Content-Length: 0
]]>
</message>
<message
from="127.0.0.11:5060"
to="127.0.0.12:5060"
time="1437463866010"
isSender="false"
transactionId="z9hg4bk-393131-d6f070870ff38a7bc7a5764e8e3f6d3b"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="SIP/2.0 100 Trying"
>
<![CDATA[SIP/2.0 100 Trying
Via: SIP/2.0/UDP 127.0.0.12:5060;branch=z9hG4bK-393131-d6f070870ff38a7bc7a5764e8e3f6d3b
From: <sip:127.0.0.12:5060>;tag=2074886745
To: <sip:alice@127.0.0.11:5060>
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
CSeq: 1 INVITE
Contact: <sip:101@127.0.0.11:5060;transport=udp>;reg-id=1
Content-Length: 0
]]>
</message>
<message
from="127.0.0.11:5060"
to="127.0.0.12:5060"
time="1437463866028"
isSender="false"
transactionId="z9hg4bk-393131-d6f070870ff38a7bc7a5764e8e3f6d3b"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="SIP/2.0 180 Ringing"
>
<![CDATA[SIP/2.0 180 Ringing
Via: SIP/2.0/UDP 127.0.0.12:5060;branch=z9hG4bK-393131-d6f070870ff38a7bc7a5764e8e3f6d3b
From: <sip:127.0.0.12:5060>;tag=2074886745
To: <sip:alice@127.0.0.11:5060>
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
CSeq: 1 INVITE
Contact: <sip:101@127.0.0.11:5060;transport=udp>;reg-id=1
Allow: INVITE,ACK,CANCEL,BYE,REFER,OPTIONS,NOTIFY,SUBSCRIBE,PRACK,MESSAGE,INFO,UPDATE
Allow-Events: talk,hold,refer,call-info
Content-Length: 0
]]>
</message>
<message
from="127.0.0.11:5060"
to="127.0.0.12:5060"
time="1437463866047"
isSender="false"
transactionId="z9hg4bk-393131-d6f070870ff38a7bc7a5764e8e3f6d3b"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="SIP/2.0 183 PROGRESS"
>
<![CDATA[SIP/2.0 183 PROGRESS
Via: SIP/2.0/UDP 127.0.0.12:5060;branch=z9hG4bK-393131-d6f070870ff38a7bc7a5764e8e3f6d3b
From: <sip:127.0.0.12:5060>;tag=2074886745
To: <sip:alice@127.0.0.11:5060>
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
CSeq: 1 INVITE
Contact: <sip:101@127.0.0.11:5060;transport=udp>;reg-id=1
Allow: INVITE,ACK,CANCEL,BYE,REFER,OPTIONS,NOTIFY,SUBSCRIBE,PRACK,MESSAGE,INFO,UPDATE
Allow-Events: talk,hold,refer,call-info
Content-Length: 0
]]>
</message>
<message
from="127.0.0.11:5060"
to="127.0.0.12:5060"
time="1437463870629"
isSender="false"
transactionId="z9hg4bk-393131-d6f070870ff38a7bc7a5764e8e3f6d3b"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="SIP/2.0 200 OK"
>
<![CDATA[SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.12:5060;branch=z9hG4bK-393131-d6f070870ff38a7bc7a5764e8e3f6d3b
From: <sip:127.0.0.12:5060>;tag=2074886745
To: <sip:alice@127.0.0.11:5060>;tag=dqixl8jjv0w
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
CSeq: 1 INVITE
Contact: <sip:101@127.0.0.11:5060;transport=udp>;reg-id=1
User-Agent: snom300/8.7.3.10
Content-Type: application/sdp
Content-Length: 161
]]>
</message>
<message
from="127.0.0.12:5060"
to="127.0.0.11:5060"
time="1437463870636"
isSender="true"
transactionId="z9hg4bk-393131-78a57efafa9f181708d9e4ee05b324a3"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="ACK sip:101@127.0.0.11:5060;transport=udp SIP/2.0"
>
<![CDATA[ACK sip:101@127.0.0.11:5060;transport=udp SIP/2.0
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
CSeq: 1 ACK
Via: SIP/2.0/UDP 127.0.0.12:5060;branch=z9hG4bK-393131-78a57efafa9f181708d9e4ee05b324a3
From: <sip:127.0.0.12:5060>;tag=2074886745
To: <sip:alice@127.0.0.11:5060>;tag=dqixl8jjv0w
Max-Forwards: 70
Content-Length: 0
]]>
</message>
<message
from="127.0.0.11:5060"
to="127.0.0.12:5060"
time="1437463873314"
isSender="false"
transactionId="z9hg4bk-xxjolo9mn9hi"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="BYE sip:null@127.0.0.12:5060 SIP/2.0"
>
<![CDATA[BYE sip:null@127.0.0.12:5060 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.11:5060;branch=z9hG4bK-xxjolo9mn9hi
From: <sip:127.0.0.12:5060>;tag=2074886745
To: <sip:alice@127.0.0.11:5060>;tag=dqixl8jjv0w
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
CSeq: 1 BYE
Max-Forwards: 70
Contact: <sip:101@127.0.0.11:5060;transport=udp>;reg-id=1
User-Agent: snom300/8.7.3.10
RTP-RxStat: Total_Rx_Pkts=815,Rx_Pkts=0,Rx_Pkts_Lost=0,Remote_Rx_Pkts_Lost=0
RTP-TxStat: Total_Tx_Pkts=812,Tx_Pkts=812,Remote_Tx_Pkts=0
Content-Length: 0
]]>
</message>
<message
from="127.0.0.12:5060"
to="127.0.0.11:5060"
time="1437463873322"
isSender="true"
transactionId="z9hg4bk-xxjolo9mn9hi"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="SIP/2.0 481 Call leg/Transaction does not exist"
>
<![CDATA[SIP/2.0 481 Call leg/Transaction does not exist
To: <sip:alice@127.0.0.11:5060>;tag=dqixl8jjv0w
Via: SIP/2.0/UDP 127.0.0.11:5060;branch=z9hG4bK-xxjolo9mn9hi
CSeq: 1 BYE
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
From: <sip:127.0.0.12:5060>;tag=2074886745
Content-Length: 0
]]>
</message>
<message
from="127.0.0.11:5060"
to="127.0.0.12:5060"
time="1437463873384"
isSender="false"
transactionId="z9hg4bk-xxjolo9mn9hi"
callId="123c727958f6588323a087db02e6a235@127.0.0.12"
firstLine="ACK sip:null@127.0.0.12:5060 SIP/2.0"
>
<![CDATA[ACK sip:null@127.0.0.12:5060 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.11:5060;branch=z9hG4bK-xxjolo9mn9hi
From: <sip:127.0.0.12:5060>;tag=2074886745
To: <sip:alice@127.0.0.11:5060>;tag=dqixl8jjv0w
Call-ID: 123c727958f6588323a087db02e6a235@127.0.0.12
CSeq: 1 ACK
Max-Forwards: 70
Route: <sip:127.0.0.12:5060;transport=udp;lr>
Content-Length: 0
]]>
</message>
Looking at the updated logs.
You send INVITE From: <sip:127.0.0.12:5060>;tag=2074886745
The remote side sends BYE again From: <sip:127.0.0.12:5060>;tag=2074886745
The endpoints are sending messages on behalf of the same address <sip:127.0.0.12:5060>
which is wrong. Your remote party should send From: <sip:alice@127.0.0.11:5060>;tag=dqixl8jjv0w
. The call leg ID is in reverse thus not found.