examples.nistgoodies.leakaudit.LeakingApp Maven / Gradle / Ivy
package examples.nistgoodies.leakaudit;
import gov.nist.javax.sip.stack.SIPDialog;
import gov.nist.javax.sip.stack.SIPClientTransaction;
import gov.nist.javax.sip.stack.SIPTransactionStack;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.address.AddressFactory;
import javax.sip.header.*;
import javax.sip.message.Request;
import javax.sip.message.Response;
import javax.sip.message.MessageFactory;
import java.util.*;
import java.text.ParseException;
/**
* This example demonstrates how an application can monitor the SIP Stack
* for leaked dialogs and transactions.
*
* This code is in the public domain.
*
* @author R. Borba (Natural Convergence)
*/
public class LeakingApp implements SipListener {
/// Dialogs indexed by call id
private Map dialogs = new HashMap();
/// Current CSeq
private long cseq = 0;
/// Stack objects
private HeaderFactory headerFactory;
private MessageFactory messageFactory;
private AddressFactory addressFactory;
private AllowHeader ALLOW;
/// Constructor
public LeakingApp() {
SipFactory l_oSipFactory = SipFactory.getInstance();
try {
headerFactory = l_oSipFactory.createHeaderFactory();
messageFactory = l_oSipFactory.createMessageFactory();
addressFactory = l_oSipFactory.createAddressFactory();
ALLOW = headerFactory.createAllowHeader(Request.REGISTER + ',' + Request.INVITE + ',' + Request.CANCEL
+ ',' + Request.ACK + ',' + Request.BYE + ',' + Request.REFER + ',' + Request.INFO);
}
catch (Exception e) {
System.out.println("LeakingApp: Error creating stack objects. Exception: " + e.toString());
}
}
// ---------------------
// SipListener interface
// ---------------------
public void processRequest(RequestEvent a_oEvent) {
Request l_oRequest = a_oEvent.getRequest();
String l_sCallID = ((CallIdHeader) l_oRequest.getHeader(CallIdHeader.NAME)).getCallId();
System.out.println("processRequest(): CallID=" + l_sCallID +
", Request= " + l_oRequest.getMethod());
}
public void processResponse(ResponseEvent a_oEvent) {
Response l_oResponse = a_oEvent.getResponse();
String l_sCallID = ((CallIdHeader) l_oResponse.getHeader(CallIdHeader.NAME)).getCallId();
System.out.println("processResponse(): CallID=" + l_sCallID +
", Response= " + l_oResponse.toString());
}
public void processTimeout(TimeoutEvent a_oEvent) {
System.out.println("processTimeout()");
}
public void processIOException(IOExceptionEvent exceptionEvent) {
System.out.println("IOExceptionEvent: " + exceptionEvent.toString());
}
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
System.out.println("TransactionTerminatedEvent: " + transactionTerminatedEvent.toString());
}
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
System.out.println("DialogTerminatedEvent: " + dialogTerminatedEvent.toString());
}
/// Creates a request containing an INVITE message
private Request createRequest() {
try {
CallIdHeader callIdHeader = LeakAudit.sipProvider.getNewCallId();
CSeqHeader cseqHeader = headerFactory.createCSeqHeader(++cseq, Request.INVITE);
SipURI requestURI = addressFactory.createSipURI("to-user", "127.0.0.1");
requestURI.setTransportParam("udp");
SipURI fromURI = addressFactory.createSipURI("from-user", LeakAudit.sipStack.getIPAddress());
Address fromAddress = addressFactory.createAddress("from-user", fromURI);
String fromTag = String.valueOf((int) (Math.random() * 10000));
FromHeader fromHeader = headerFactory.createFromHeader(fromAddress, fromTag);
SipURI toURI = addressFactory.createSipURI("to-user", "127.0.0.1");
Address toAddress = addressFactory.createAddress("to-user", toURI);
String toTag = String.valueOf((int) (Math.random() * 10000));
ToHeader toHeader = headerFactory.createToHeader(toAddress, toTag);
ListeningPoint listeningPoint = LeakAudit.sipProvider.getListeningPoints()[0];
ViaHeader viaHeader = headerFactory.createViaHeader(LeakAudit.sipStack.getIPAddress(),
listeningPoint.getPort(),
listeningPoint.getTransport(),
null);
// add via headers
ArrayList viaList = new ArrayList();
viaList.add(viaHeader);
MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);
Request request = messageFactory.createRequest(requestURI,
Request.INVITE,
callIdHeader,
cseqHeader,
fromHeader,
toHeader,
viaList,
maxForwards);
// Add the Contact header
SipURI sipUri = addressFactory.createSipURI(null, LeakAudit.sipStack.getIPAddress());
Address contactAddress = addressFactory.createAddress(sipUri);
ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
request.addHeader(contactHeader);
// Add Allow headers
request.addHeader(ALLOW);
return request;
}
catch (ParseException e) {
System.err.println("ParseException " + e.getMessage());
}
catch (InvalidArgumentException e) {
System.err.println("InvalidArgumentException " + e.getMessage());
}
catch (Exception e) {
System.err.println("Exception " + e.getMessage());
}
return null;
}
// Creates a transaction for this request
private ClientTransaction createTransaction(Request request) {
try {
return LeakAudit.sipProvider.getNewClientTransaction(request);
}
catch (Exception e) {
System.err.println("Exception " + e.getMessage());
}
return null;
}
/// Sends an INVITE request to a dummy location
public void sendRequest() {
try {
// Create the request and the transaction
Request request = createRequest();
ClientTransaction transaction = createTransaction(request);
// Send the request
// System.out.println("Sending Request: " + request.toString());
transaction.sendRequest();
// Remember this call id and this transaction
CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
dialogs.put(callIdHeader.getCallId(), transaction);
System.out.println("Sent INVITE, Call ID = " + callIdHeader.getCallId());
}
catch (Exception e) {
System.err.println("Exception " + e.getMessage());
}
}
/// Leaks a dialog into the stack
public void leakDialog() {
// Insert a foreign dialog from nowhere just so we can detect it
// Note: Normally we would ask the application to "forget" about one of its call ids by removing one of
// the entries in the "dialogs" hashmap". However, the stack only creates a dialog for a client transaction
// *after* the client transaction gets a response. Since our little example is not getting any response for
// its INVITEs (there's nobody there to respond), removing a dialog from its hashmap doesn't have any effect
// on this test. So, we have to do it the hard way, i.e., insert a fake dialog by force into the stack and
// wait until it is detected as leaked.
// You should see something like this at the console:
//
// Leaked dialogs:
// dialog id: 1234, dialog state: null
// Total: 1 leaked dialogs detected and removed.
//
// Also notice that leaked transactions are a little harder to simulate so I'm not even trying in this example.
Request request = createRequest();
SIPClientTransaction transaction = (SIPClientTransaction) createTransaction(request);
SIPDialog dialog = ((SIPTransactionStack) LeakAudit.sipStack).createDialog(transaction);
dialog.setDialogId("1234");
((SIPTransactionStack) LeakAudit.sipStack).putDialog(dialog);
System.out.println("Intentionally inserted a leaked dialog, CallID = " + dialog.getCallId());
}
/// Returns a list (set) of active call IDs used by this application
public Set getActiveCallIDs() {
return dialogs.keySet();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy