package sip; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.Properties; import java.util.TooManyListenersException; import javax.sip.ClientTransaction; import javax.sip.DialogTerminatedEvent; import javax.sip.IOExceptionEvent; import javax.sip.InvalidArgumentException; import javax.sip.ListeningPoint; import javax.sip.ObjectInUseException; import javax.sip.PeerUnavailableException; import javax.sip.RequestEvent; import javax.sip.ResponseEvent; import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.SipFactory; import javax.sip.SipListener; import javax.sip.SipProvider; import javax.sip.SipStack; import javax.sip.TimeoutEvent; import javax.sip.TransactionAlreadyExistsException; import javax.sip.TransactionTerminatedEvent; import javax.sip.TransactionUnavailableException; import javax.sip.TransportNotSupportedException; import javax.sip.address.Address; import javax.sip.address.AddressFactory; import javax.sip.address.SipURI; import javax.sip.header.CSeqHeader; import javax.sip.header.CallIdHeader; import javax.sip.header.ContactHeader; import javax.sip.header.FromHeader; import javax.sip.header.Header; import javax.sip.header.HeaderFactory; import javax.sip.header.MaxForwardsHeader; import javax.sip.header.ToHeader; import javax.sip.header.ViaHeader; import javax.sip.message.MessageFactory; import javax.sip.message.Request; import javax.sip.message.Response; import org.apache.log4j.Logger; public class SIPLayer implements SipListener { private static final Logger LOGGER = Logger.getLogger("SIPLayerLogger"); static final String PROTOCOL = "udp"; public final long INVITE_SEQUENCE_NUMBER = 1; private String username; private ArrayList<IMessageProcessor> observers; private SipStack sipStack; private SipFactory sipFactory; private AddressFactory addressFactory; private HeaderFactory headerFactory; private MessageFactory messageFactory; private SipProvider sipProvider; private String host; private int port; public SIPLayer(String username, String ip, int port) throws PeerUnavailableException, TransportNotSupportedException, InvalidArgumentException, ObjectInUseException, TooManyListenersException { this.host = ip; this.port = port; setUsername(username); this.observers = new ArrayList<IMessageProcessor>(); sipFactory = SipFactory.getInstance(); // Sets the pathname that identifies the location of a particular // vendor's implementation of this specification. sipFactory.setPathName("gov.nist"); Properties properties = new Properties(); properties.setProperty("javax.sip.STACK_NAME", "SIPLayer"); properties.setProperty("javax.sip.IP_ADDRESS", ip); // SipFactory / AddressFactory / HeaderFactory / MessageFactory // Factory classes to create the various objects of the system. They // return objects that implement standard interface. sipStack = sipFactory.createSipStack(properties); headerFactory = sipFactory.createHeaderFactory(); addressFactory = sipFactory.createAddressFactory(); messageFactory = sipFactory.createMessageFactory(); // SipStack - The first interface you'll need, used to create // ListeningPoints and SipProviders. // ListeningPoint - This interface encapsulates a transport/port pair ListeningPoint protocol = sipStack.createListeningPoint(ip, port, PROTOCOL); // SipProvider - register a listener for incoming SIP messages using // this interface sipProvider = sipStack.createSipProvider(protocol); sipProvider.addSipListener(this); } public void registerObserver(IMessageProcessor mp) { LOGGER.debug("registerObserver()"); observers.add(mp); } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } private String getHost() { return this.host; } private int getPort() { return this.port; } public ClientTransaction sendInvite(String user, String host, String type) throws ParseException, InvalidArgumentException, SipException { LOGGER.debug("send(" + user + ", " + host + ", " + type + " )"); String dialogId; // Create Main Elements // Creates a SipURI based on the given user and host components SipURI from = addressFactory.createSipURI(getUsername(), getHost() + ":" + getPort()); // Creates an Address with the new URI attribute value Address fromNameAddress = addressFactory.createAddress(from); // Sets the display name of the Address. fromNameAddress.setDisplayName(getUsername()); // Creates a new FromHeader based on the newly supplied address and tag // values. FromHeader fromHeader = headerFactory.createFromHeader(fromNameAddress, "SteenbuckFooHarms"); SipURI to = addressFactory.createSipURI(user, host + ":" + getPort()); // Creates an Address with the new URI attribute value Address toNameAddress = addressFactory.createAddress(to); // Sets the display name of the Address. toNameAddress.setDisplayName(user); // To: Header = From: Header at Registration ToHeader toHeader = headerFactory.createToHeader(toNameAddress, null); // Create RequestUri and define Transportprotocol SipURI requestURI = addressFactory.createSipURI(user, host); requestURI.setTransportParam(PROTOCOL); // Create Via Header ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); ViaHeader viaHeader = headerFactory.createViaHeader(getHost(), getPort(), PROTOCOL, null); viaHeaders.add(viaHeader); CallIdHeader callIdHeader = sipProvider.getNewCallId(); long sequenceNumber = INVITE_SEQUENCE_NUMBER; CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(sequenceNumber, type); MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70); // Create Register Request request = messageFactory.createRequest(requestURI, type, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards); // Complete Register SipURI contactURI = addressFactory.createSipURI(getUsername(), getHost()); contactURI.setPort(getPort()); Address contactAddress = addressFactory.createAddress(contactURI); contactAddress.setDisplayName(getUsername()); ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress); request.addHeader(contactHeader); // Send Message ClientTransaction trans; if (type == Request.INVITE) { trans = sipProvider.getNewClientTransaction(request); LOGGER.trace("GESENDET: \n" + request.toString()); trans.sendRequest(); } else { throw new RuntimeException("Request should be send statefull" + request.toString()); } // return callIdHeader.getCallId(); return trans; } /** * @param proxyAddress * @param proxyPort * @return CallId as String * @throws ParseException * @throws InvalidArgumentException * @throws SipException */ public String registerAtProxy(String proxyAddress, int proxyPort) throws ParseException, InvalidArgumentException, SipException { LOGGER.debug("registerAtProxy(" + proxyAddress + ", " + proxyPort + " )"); // Create Main Elements // Creates a SipURI based on the given user and host components SipURI from = addressFactory.createSipURI(getUsername(), getHost() + ":" + getPort()); // Creates an Address with the new URI attribute value Address fromNameAddress = addressFactory.createAddress(from); // Sets the display name of the Address. fromNameAddress.setDisplayName(getUsername()); // Creates a new FromHeader based on the newly supplied address and tag // values. FromHeader fromHeader = headerFactory.createFromHeader(fromNameAddress, "SteenbuckFooHarmsRegister"); // To: Header = From: Header at Registration ToHeader toHeader = headerFactory.createToHeader(fromNameAddress, null); // Create RequestUri and define Transportprotocol SipURI requestURI = addressFactory.createSipURI("registrar", proxyAddress); requestURI.setTransportParam(PROTOCOL); // Create Via Header ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); ViaHeader viaHeader = headerFactory.createViaHeader(getHost(), getPort(), PROTOCOL, null); viaHeaders.add(viaHeader); CallIdHeader callIdHeader = sipProvider.getNewCallId(); long sequenceNumber = 1; CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(sequenceNumber, Request.REGISTER); MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70); // Create Register Request request = messageFactory.createRequest(requestURI, Request.REGISTER, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards); // Complete Register SipURI contactURI = addressFactory.createSipURI(getUsername(), getHost()); contactURI.setPort(getPort()); Address contactAddress = addressFactory.createAddress(contactURI); contactAddress.setDisplayName(getUsername()); ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress); request.addHeader(contactHeader); // Send Message LOGGER.trace(request.toString()); sipProvider.sendRequest(request); return callIdHeader.getCallId(); } @Override public void processDialogTerminated(DialogTerminatedEvent dte) { LOGGER.debug("processDialogTerminated(" + dte.toString() + " )"); for (IMessageProcessor mp : observers) { mp.processDialogTerminated(dte); } } @Override public void processIOException(IOExceptionEvent ioEx) { LOGGER.debug("processDialogTerminated(" + ioEx.toString() + " )"); } @Override public void processRequest(RequestEvent requestEvent) { LOGGER.debug("processRequest(" + requestEvent.toString() + " )"); try { Request request = requestEvent.getRequest(); String method = request.getMethod(); if (method.equals(Request.INVITE)) { for (IMessageProcessor mp : observers) { mp.processInvite(requestEvent); } } else if (method.equals(Request.BYE)) { for (IMessageProcessor mp : observers) { mp.processBye(requestEvent); } } else if (method.equals(Request.ACK)) { for (IMessageProcessor mp : observers) { mp.processAck(requestEvent); } } } catch (Exception e) { throw new RuntimeException(e); } } @Override public void processResponse(ResponseEvent responseEvent) { LOGGER.debug("processResponse(" + responseEvent.toString() + " )"); Response response = responseEvent.getResponse(); int status = response.getStatusCode(); LOGGER.trace("ERHALTEN \n" + response.toString()); switch (status) { case Response.TRYING: for (IMessageProcessor mp : observers) { mp.processTrying(); } break; case Response.OK: for (IMessageProcessor mp : observers) { mp.processOK(responseEvent); } break; case Response.RINGING: for (IMessageProcessor mp : observers) { mp.processRinging(); } break; default: break; } } static public String getCallId(ResponseEvent responseEvent) { return getCallId(responseEvent.getResponse().getHeader(CallIdHeader.NAME)); } private static String getCallId(Header header) { CallIdHeader callIdHeader = (CallIdHeader) header; return callIdHeader.getCallId(); } public static String getCallId(RequestEvent requestEvent) { return getCallId(requestEvent.getRequest().getHeader(CallIdHeader.NAME)); } @Override public void processTimeout(TimeoutEvent timeOutEvent) { LOGGER.debug("processTimeout(" + timeOutEvent.toString() + " )"); } @Override public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { LOGGER.debug("processTransactionTerminated(" + transactionTerminatedEvent.toString() + " )"); } public ContactHeader getContactHeader() { try { SipURI contactURI = addressFactory.createSipURI(getUsername(), getHost()); contactURI.setPort(getPort()); Address contactAddress = addressFactory.createAddress(contactURI); contactAddress.setDisplayName(getUsername()); ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress); return contactHeader; } catch (ParseException e) { throw new RuntimeException("Could not get contact address", e); } } public Response createResponse(int arg0, Request arg1) { LOGGER.debug("createResponse()"); try { return messageFactory.createResponse(arg0, arg1); } catch (ParseException e) { LOGGER.error("Could not generate: ", e); throw new RuntimeException(e); } } public void sendResponse(Response response) { LOGGER.debug("sendResponse()"); LOGGER.trace(response.toString()); try { sipProvider.sendResponse(response); } catch (SipException e) { LOGGER.error("Could not send: ", e); } } public ServerTransaction getNewServerTransaction(Request arg0) throws TransactionAlreadyExistsException, TransactionUnavailableException { LOGGER.debug("getNewServerTransaction()"); return sipProvider.getNewServerTransaction(arg0); } public ClientTransaction getNewClientTransaction(Request arg0) throws TransactionUnavailableException { LOGGER.debug("getNewClientTransaction()"); return sipProvider.getNewClientTransaction(arg0); } }