为什么 jain sip return 481 收到再见?
why jain sip return 481 on received bye?
我使用 Jain Sip 创建一个 sip 应用程序。它可以send/receiveINVITE/ACK/BYE,必要时用SDP发回响应。
但是当它收到对方的 BYE 时,Jain Sip 会抛出一个 481。
我试图弄清楚发生了什么事一个星期仍然不明白。
我使用来自传入请求的 ServerTransaction.sendResponse 有状态地发送响应。自动对话已打开。
这里是完整的源码(界面我用的是swing)
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());
}
}
这里是log(没有收到client发送的bye,client收到的481 Callleg/Transaction不存在)
日志
<!-- 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>
正在查看更新的日志。
您发送邀请 From: <sip:127.0.0.12:5060>;tag=2074886745
对端再次发送BYEFrom: <sip:127.0.0.12:5060>;tag=2074886745
端点代表同一地址发送消息 <sip:127.0.0.12:5060>
这是错误的。您的远程方应发送 From: <sip:alice@127.0.0.11:5060>;tag=dqixl8jjv0w
。呼叫段 ID 倒序,因此未找到。
我使用 Jain Sip 创建一个 sip 应用程序。它可以send/receiveINVITE/ACK/BYE,必要时用SDP发回响应。 但是当它收到对方的 BYE 时,Jain Sip 会抛出一个 481。 我试图弄清楚发生了什么事一个星期仍然不明白。
我使用来自传入请求的 ServerTransaction.sendResponse 有状态地发送响应。自动对话已打开。
这里是完整的源码(界面我用的是swing)
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());
}
}
这里是log(没有收到client发送的bye,client收到的481 Callleg/Transaction不存在)
日志
<!-- 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>
正在查看更新的日志。
您发送邀请 From: <sip:127.0.0.12:5060>;tag=2074886745
对端再次发送BYEFrom: <sip:127.0.0.12:5060>;tag=2074886745
端点代表同一地址发送消息 <sip:127.0.0.12:5060>
这是错误的。您的远程方应发送 From: <sip:alice@127.0.0.11:5060>;tag=dqixl8jjv0w
。呼叫段 ID 倒序,因此未找到。