package org.mobicents.slee.resource.sip11; import gov.nist.javax.sip.address.SipUri; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.ParseException; import java.util.HashSet; import java.util.Set; import java.util.TooManyListenersException; import javax.sip.ClientTransaction; import javax.sip.Dialog; import javax.sip.InvalidArgumentException; import javax.sip.ListeningPoint; import javax.sip.ObjectInUseException; import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.SipListener; import javax.sip.SipProvider; import javax.sip.SipStack; import javax.sip.Transaction; import javax.sip.TransactionAlreadyExistsException; import javax.sip.TransactionUnavailableException; import javax.sip.TransportAlreadySupportedException; import javax.sip.address.Address; import javax.sip.address.AddressFactory; import javax.sip.address.SipURI; import javax.sip.header.CallIdHeader; import javax.sip.header.HeaderFactory; import javax.sip.header.ViaHeader; import javax.sip.message.MessageFactory; import javax.sip.message.Request; import javax.sip.message.Response; import javax.slee.facilities.Tracer; import net.java.slee.resource.sip.CancelRequestEvent; import net.java.slee.resource.sip.DialogActivity; import net.java.slee.resource.sip.SleeSipProvider; import org.mobicents.slee.resource.sip11.wrappers.ClientTransactionWrapper; import org.mobicents.slee.resource.sip11.wrappers.DialogWrapper; import org.mobicents.slee.resource.sip11.wrappers.ServerTransactionWrapper; import org.mobicents.slee.resource.sip11.wrappers.SuperTransactionWrapper; public class SleeSipProviderImpl implements SleeSipProvider { protected AddressFactory addressFactory = null; protected HeaderFactory headerFactory = null; protected MessageFactory messageFactory = null; protected SipStack stack = null; protected SipResourceAdaptor ra = null; protected SipProvider provider = null; protected final Tracer tracer; public SleeSipProviderImpl(AddressFactory addressFactory, HeaderFactory headerFactory, MessageFactory messageFactory, SipStack stack, SipResourceAdaptor ra, SipProvider provider) { super(); this.addressFactory = addressFactory; this.headerFactory = headerFactory; this.messageFactory = messageFactory; this.stack = stack; this.ra = ra; this.provider = provider; this.tracer = ra.getRaContext().getTracer(SleeSipProviderImpl.class.getSimpleName()); } public AddressFactory getAddressFactory() { return this.addressFactory; } public HeaderFactory getHeaderFactory() { return this.headerFactory; } public SipURI getLocalSipURI(String transport) { ListeningPoint lp = this.provider.getListeningPoint(transport); SipURI uri = null; if (lp != null) { try { uri = new SipUri(); uri.setHost(lp.getIPAddress()); uri.setPort(lp.getPort()); uri.setTransportParam(transport); } catch (ParseException e) { tracer.severe("Failed parsing LP info. Failed to parse listening point for transport [" + transport + "] [" + lp + "]",e); } return uri; } else { if (tracer.isFineEnabled()) { tracer .fine("Failed parsing LP info. No listening point for transport [" + transport + "] [" + lp + "]"); } return null; } } public ViaHeader getLocalVia(String transport, String branch) { try { SipURI uri = this.getLocalSipURI(transport); if (uri == null) { return null; } return this.headerFactory.createViaHeader(uri.getHost(), uri .getPort(), transport, branch); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvalidArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public MessageFactory getMessageFactory() { return this.messageFactory; } public boolean isLocalHostname(String host) { try { InetAddress[] addresses = InetAddress.getAllByName(host); Set<InetAddress> stackAddresses = new HashSet<InetAddress>(); for (ListeningPoint lp : this.provider.getListeningPoints()) { InetAddress tmp = InetAddress.getByName(lp.getIPAddress()); if (tmp != null) stackAddresses.add(tmp); } for(InetAddress ia:addresses) { if(stackAddresses.contains(ia)) return true; } } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } public boolean isLocalSipURI(SipURI uri) { // XXX: InetAddress api is // crude.....!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ListeningPoint lp = this.provider.getListeningPoint(uri .getTransportParam()); if (lp != null && lp.getIPAddress().equals(uri.getHost()) && lp.getPort() == uri.getPort()) { return true; } else { if (tracer.isFineEnabled()) { tracer .fine("Passed uri not local? Passed URI[" + uri + "] doesnt match lp[" + lp + "]"); } return false; } } public void addListeningPoint(ListeningPoint arg0) throws ObjectInUseException, TransportAlreadySupportedException { throw new UnsupportedOperationException("No dynamic change to LP"); } public void addSipListener(SipListener arg0) throws TooManyListenersException { throw new TooManyListenersException( "RA can be the only Listener for this stack!!"); } @SuppressWarnings("deprecation") public ListeningPoint getListeningPoint() { return this.provider.getListeningPoint(); } public ListeningPoint getListeningPoint(String arg0) { return this.provider.getListeningPoint(arg0); } public ListeningPoint[] getListeningPoints() { return this.provider.getListeningPoints(); } public CallIdHeader getNewCallId() { return this.provider.getNewCallId(); } public ServerTransaction getNewServerTransaction(Request arg0) throws TransactionAlreadyExistsException, TransactionUnavailableException { return this.getNewServerTransaction(arg0,null,true); } public SipStack getSipStack() { throw new UnsupportedOperationException( "This operation is not supported yet"); } public void removeListeningPoint(ListeningPoint arg0) throws ObjectInUseException { throw new UnsupportedOperationException( "This operation is not supported yet"); } public void removeSipListener(SipListener arg0) { throw new UnsupportedOperationException( "This operation is not supported yet"); } public void sendRequest(Request arg0) throws SipException { this.provider.sendRequest(arg0); } public void sendResponse(Response arg0) throws SipException { this.provider.sendResponse(arg0); } public void setAutomaticDialogSupportEnabled(boolean arg0) { this.provider.setAutomaticDialogSupportEnabled(arg0); } public void setListeningPoint(ListeningPoint arg0) throws ObjectInUseException { throw new UnsupportedOperationException( "This operation is not supported yet"); } public ClientTransaction getNewClientTransaction(Request request, boolean createActivity) throws TransactionUnavailableException { ClientTransaction ct = provider.getNewClientTransaction(request); ClientTransactionWrapper ctw = new ClientTransactionWrapper(ct); DialogWrapper dw = null; if (ct.getDialog() != null && ct.getDialog().getApplicationData() instanceof DialogWrapper) { dw = (DialogWrapper) ct.getDialog().getApplicationData(); dw.addOngoingTransaction(ctw); } // add transaction to activities if it's dialog not exists and is an activity // considering that if dw exists then it's an activity if (dw == null) { if(createActivity) { ra.addActivity(ctw.getActivityHandle(), ctw); } } return ctw; } public ClientTransaction getNewClientTransaction(Request request) throws TransactionUnavailableException { return this.getNewClientTransaction(request,true); } /** * getNewServerTransaction * * @param request * Request * @return ServerTransaction * @throws TransactionAlreadyExistsException * @throws TransactionUnavailableException */ public ServerTransaction getNewServerTransaction(Request request, ServerTransaction serverTransaction, boolean createActivityInSlee) throws TransactionAlreadyExistsException, TransactionUnavailableException { // TODO: add checks for wrapper if(serverTransaction == null) { serverTransaction = provider.getNewServerTransaction(request); } ServerTransactionWrapper stw = new ServerTransactionWrapper(serverTransaction); DialogWrapper dw = null; if (serverTransaction.getDialog() != null && serverTransaction.getDialog().getApplicationData() instanceof DialogWrapper) { dw = (DialogWrapper) serverTransaction.getDialog().getApplicationData(); dw.addOngoingTransaction(stw); } // add transaction to activities if its dialog does not exists or is not an activity // considering that if dw exists then it's an activity if (dw == null) { if (createActivityInSlee) { ra.addActivity(stw.getActivityHandle(), stw); } } return stw; } /** * @param transaction * - object implementing <b>javax.sip.Transaction</b> interface * for which dialog should be obtained * * @return Newly created dialog for transaction object. * @throws TransactionAlreadyExistsException * @throws TransactionUnavailableException */ public Dialog getNewDialog(Transaction transaction) throws SipException { // TODO: add checks for wrapper return this.getNewDialog(transaction, null, true); } public Dialog getNewDialog(Transaction transaction, SipActivityHandle forkMaster, boolean makeWrapper) throws SipException { // TODO: add checks for wrapper SuperTransactionWrapper stw = (SuperTransactionWrapper) transaction; Transaction t = (Transaction) stw.getWrappedTransaction(); Dialog d = provider.getNewDialog(t); if (makeWrapper) { DialogWrapper dw = getNewDialogActivity(d, forkMaster, stw); //if (!d.isServer()) { // ra.addClientDialogMaping(d.getLocalTag() + "_" + d.getCallId().getCallId(), dw.getActivityHandle()); //} return dw; } else { return d; } } public DialogWrapper getNewDialogActivity(Dialog d, SipActivityHandle forkMaster, SuperTransactionWrapper stw) { //FIXME: this is a bit dangerous, we should hide this method ^ // Here dialog exists, we just need another wrapper for this activity DialogWrapper dw = new DialogWrapper(d, forkMaster, this, ra); if (stw != null) if (stw instanceof ServerTransactionWrapper) { dw.addOngoingTransaction((ServerTransactionWrapper) stw); } else if (stw instanceof ClientTransactionWrapper) { dw.addOngoingTransaction((ClientTransactionWrapper) stw); } else { tracer.severe("Unknown type " + stw.getClass() + " of SIP Transaction, can't add to dialog wrapper"); } ra.addActivity(dw.getActivityHandle(), dw); return dw; } public DialogActivity getNewDialog(Address from, Address to) throws SipException { if (from == null) { throw new IllegalArgumentException("From address cant be null"); } if (to == null) { throw new IllegalArgumentException("To address cant be null"); } return getNewDialog(from, to, null); } public DialogActivity getNewDialog(DialogActivity incomingDialog, boolean useSameCallId) throws SipException { if (incomingDialog == null || !incomingDialog.isServer()) { throw new IllegalArgumentException("Incoming dialog is either null or is UAC dialog!!"); } CallIdHeader callIdHeader = null; if (useSameCallId) { callIdHeader = incomingDialog.getCallId(); } DialogWrapper dw = (DialogWrapper) getNewDialog(incomingDialog.getRemoteParty(),incomingDialog.getLocalParty(), callIdHeader); return dw; } private DialogActivity getNewDialog(Address from, Address to, CallIdHeader callIdHeader) throws SipException { DialogWrapper dw = new DialogWrapper(this, ra); dw.setFromAddress(from); dw.setToAddress(to); ra.addActivity(dw.getActivityHandle(), dw); if(callIdHeader == null) { callIdHeader = provider.getNewCallId(); } dw.setCallIdToReUse(callIdHeader); return dw; } public boolean acceptCancel(CancelRequestEvent cancelEvent, boolean isProxy) { if (cancelEvent.getMatchingTransaction() != null) { try { Response response = this.getMessageFactory().createResponse( Response.OK, cancelEvent.getRequest()); cancelEvent.getServerTransaction().sendResponse(response); } catch (Exception e) { // specs doesn't provide any throws clause throw new RuntimeException(e.getMessage(),e); } if (!isProxy) try { Response response = this.getMessageFactory() .createResponse( Response.REQUEST_TERMINATED, cancelEvent.getMatchingTransaction() .getRequest()); cancelEvent.getMatchingTransaction().sendResponse(response); } catch (Exception e) { // specs doesn't provide any throws clause throw new RuntimeException(e.getMessage(),e); } return true; } else { if (!isProxy) { try { Response txDoesNotExistsResponse = this .getMessageFactory() .createResponse( Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST, cancelEvent.getRequest()); // provider.sendResponse(txDoesNotExistsResponse); cancelEvent.getServerTransaction().sendResponse( txDoesNotExistsResponse); } catch (Exception e) { // specs doesn't provide any throws clause throw new RuntimeException(e.getMessage(),e); } } return false; } } public DialogActivity forwardForkedResponse( ServerTransaction origServerTransaction, Response response) throws SipException { // TODO Auto-generated method stub return null; } }