diff --git a/p2pproxy/src/org/linphone/p2pproxy/core/NetworkResources.java b/p2pproxy/src/org/linphone/p2pproxy/core/NetworkResources.java index efdc7e0b7..3d1442a44 100644 --- a/p2pproxy/src/org/linphone/p2pproxy/core/NetworkResources.java +++ b/p2pproxy/src/org/linphone/p2pproxy/core/NetworkResources.java @@ -25,12 +25,12 @@ import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; -import org.linphone.p2pproxy.core.media.jxtaudpproxy.RtpSession; + import org.linphone.p2pproxy.core.media.jxtaudpproxy.RtpSessionImpl; import net.jxta.discovery.DiscoveryService; import net.jxta.pipe.InputPipe; -import net.jxta.pipe.OutputPipe; + import net.jxta.pipe.PipeMsgListener; /** diff --git a/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/JxtaSipProxy.java b/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/JxtaSipProxy.java new file mode 100644 index 000000000..1604b69dd --- /dev/null +++ b/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/JxtaSipProxy.java @@ -0,0 +1,215 @@ +/* +p2pproxy Copyright (C) 2007 Jehan Monnier () + +JxtaSipProxy.java - . + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package org.linphone.p2pproxy.core.sipproxy; + +import java.io.IOException; +import java.util.Map; + +import net.jxta.document.Advertisement; +import net.jxta.endpoint.MessageElement; +import net.jxta.endpoint.StringMessageElement; +import net.jxta.pipe.OutputPipe; +import net.jxta.pipe.PipeMsgEvent; +import net.jxta.pipe.PipeMsgListener; +import net.jxta.protocol.PipeAdvertisement; + +import org.apache.log4j.Logger; +import org.linphone.p2pproxy.api.P2pProxyException; +import org.linphone.p2pproxy.api.P2pProxyRtpRelayManagement; +import org.linphone.p2pproxy.api.P2pProxyUserNotFoundException; +import org.linphone.p2pproxy.core.JxtaNetworkManager; +import org.linphone.p2pproxy.core.P2pProxyAdvertisementNotFoundException; +import org.linphone.p2pproxy.core.media.rtprelay.SdpProcessorImpl; +import org.zoolu.sip.address.NameAddress; +import org.zoolu.sip.address.SipURL; +import org.zoolu.sip.header.MultipleHeader; +import org.zoolu.sip.header.RouteHeader; +import org.zoolu.sip.message.Message; +import org.zoolu.sip.message.MessageFactory; +import org.zoolu.sip.provider.SipProvider; +import org.zoolu.sip.transaction.TransactionServer; + +public class JxtaSipProxy implements SipProxy, PipeMsgListener { + private final JxtaNetworkManager mJxtaNetworkManager; + private final Map mRegistrationTab; + private final SdpProcessor mSdpProcessor; + private final SipProvider mProvider; + + private final static Logger mLog = Logger.getLogger(JxtaSipProxy.class); + + public JxtaSipProxy(SipProvider aProvider,JxtaNetworkManager aJxtaNetworkManager, Map aRegistrationTab,P2pProxyRtpRelayManagement aP2pProxyRtpRelayManagement) { + mJxtaNetworkManager = aJxtaNetworkManager; + mSdpProcessor = new SdpProcessorImpl(aP2pProxyRtpRelayManagement); + mRegistrationTab = aRegistrationTab; + mProvider = aProvider; + } + public void proxyRequest(SipProvider aProvider, Message aMessage) throws P2pProxyException { + + + if (aMessage.isAck() && aMessage.getToHeader().getTag() == null) { + // just terminate the Invite transaction + return; + } + + if (aMessage.isInvite() == true) { + // 100 trying + TransactionServer lTransactionServer = new TransactionServer(aProvider,aMessage,null); + Message l100Trying = MessageFactory.createResponse(aMessage,100,"trying",null); + lTransactionServer.respondWith(l100Trying); + } + + String lTo = aMessage.getToHeader().getNameAddress().getAddress().toString(); + //remove route + MultipleHeader lMultipleRoute = aMessage.getRoutes(); + if (lMultipleRoute != null) { + lMultipleRoute.removeTop(); + aMessage.setRoutes(lMultipleRoute); + } + // add Via only udp + SipUtils.addVia(aProvider,aMessage); + // add recordRoute + SipUtils.addRecordRoute(aProvider,aMessage); + try { + mSdpProcessor.processSdpBeforeSendingToPipe(aMessage); + // proxy message to pipe + OutputPipe lOutputPipe = sendMessageToPipe(lTo,aMessage.toString()); + mSdpProcessor.processSdpAfterSentToPipe( aMessage,lOutputPipe); + } catch (P2pProxyUserNotFoundException e) { + //remove via + SipUtils.removeVia(aProvider, aMessage); + if (aMessage.isInvite()) { + Message lresp = MessageFactory.createResponse(aMessage,404,e.getMessage(),null); + TransactionServer lTransactionServer = new TransactionServer(aProvider,aMessage,null); + lTransactionServer.respondWith(lresp); + } else { + throw e; + } + } catch (Exception e2) { + //remove via + SipUtils.removeVia(aProvider, aMessage); + throw new P2pProxyException(e2); + + } + + + } + + public void proxyResponse(SipProvider aProvider, Message aMessage) throws P2pProxyException { + try { + String lFrom = aMessage.getFromHeader().getNameAddress().getAddress().toString(); + mSdpProcessor.processSdpBeforeSendingToPipe(aMessage); + OutputPipe lOutputPipe = sendMessageToPipe(lFrom,aMessage.toString()); + mSdpProcessor.processSdpAfterSentToPipe( aMessage,lOutputPipe); + } catch(Exception e) { + throw new P2pProxyException(e); + } + + } + private Advertisement getPipeAdv(String aUser,long aDiscoveryTimout,boolean isTryFromLocal) throws InterruptedException, P2pProxyUserNotFoundException, IOException { + // search on all peers + try { + return mJxtaNetworkManager.getAdvertisement(null,aUser, isTryFromLocal); + } catch (P2pProxyAdvertisementNotFoundException e) { + throw new P2pProxyUserNotFoundException(e); + } + } + private OutputPipe sendMessageToPipe(String aDestination,String lContent) throws NumberFormatException, InterruptedException, P2pProxyException, IOException { + + //1 search for pipe + long lTimeout = JxtaNetworkManager.ADV_DISCOVERY_TIMEOUT_INT; + PipeAdvertisement lPipeAdvertisement = (PipeAdvertisement)getPipeAdv(aDestination,lTimeout,true); + OutputPipe lOutputPipe=null; + try { + // create output pipe + lOutputPipe = mJxtaNetworkManager.getPeerGroup().getPipeService().createOutputPipe(lPipeAdvertisement, lTimeout); + //create the message + } catch (IOException e) { + //second try from remote only to avoid wrong cached value + mJxtaNetworkManager.getPeerGroup().getDiscoveryService().flushAdvertisement(lPipeAdvertisement); + mLog.warn("cannot create output pipe, trying to ask from rdv ",e); + lPipeAdvertisement = (PipeAdvertisement)getPipeAdv(aDestination,lTimeout,false); + lOutputPipe = mJxtaNetworkManager.getPeerGroup().getPipeService().createOutputPipe(lPipeAdvertisement, lTimeout); + } + net.jxta.endpoint.Message lMessage = new net.jxta.endpoint.Message(); + StringMessageElement lStringMessageElement = new StringMessageElement("SIP", lContent, null); + lMessage.addMessageElement("SIP", lStringMessageElement); + //send the message + lOutputPipe.send(lMessage); + mLog.debug("message sent to ["+aDestination+"]"); + return lOutputPipe; + + } +////////////////////////////////////////////////////////////////////// +////jxta service methods +///////////////////////////////////////////////////////////////////// + + + public void pipeMsgEvent(PipeMsgEvent anEvent) { + MessageElement lMessageElement = anEvent.getMessage().getMessageElement("SIP"); + if (lMessageElement == null) { + //nop, this is not for me + return; + } + String lMesssage = lMessageElement.toString(); + mLog.info("pipe event sip message["+lMesssage+"]"); + Message lSipMessage = new Message(lMesssage); + // process request + if (lSipMessage.isRequest()) { + SipURL lNextHope ; + // get next hope from registrar + String lToName = lSipMessage.getToHeader().getNameAddress().getAddress().toString(); + if (mRegistrationTab.containsKey(lToName)) { + lNextHope = new SipURL(mRegistrationTab.get(lToName).Contact); + } else { + mLog.error("user ["+lToName+"] not found"); + return; + } + //RequestLine lRequestLine = new RequestLine(lSipMessage.getRequestLine().getMethod(),lNextHope); + //lSipMessage.setRequestLine(lRequestLine); + MultipleHeader lMultipleRoute = lSipMessage.getRoutes(); + RouteHeader lRouteHeader = new RouteHeader(new NameAddress(lNextHope+";lr")); + //lRouteHeader.setParameter("lr", null); + if (lMultipleRoute != null) { + lMultipleRoute.addTop(lRouteHeader); + lSipMessage.setRoutes(lMultipleRoute); + } else { + lSipMessage.addRouteHeader(lRouteHeader); + } + // add Via only udp + SipUtils.addVia(mProvider,lSipMessage); + // add recordRoute + SipUtils.addRecordRoute(mProvider,lSipMessage); + + } else { + //response + //1 remove via header + SipUtils.removeVia(mProvider,lSipMessage); + } + try { + mSdpProcessor.processSdpBeforeSendingToSipUA( lSipMessage); + } catch (P2pProxyException e) { + mLog.error("enable to re-write sdp",e); + } + + mProvider.sendMessage(lSipMessage); + // + } + +} diff --git a/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipProxy.java b/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipProxy.java new file mode 100644 index 000000000..fcc16ce3e --- /dev/null +++ b/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipProxy.java @@ -0,0 +1,29 @@ +/* +p2pproxy Copyright (C) 2007 Jehan Monnier () + +SipProxy.java - . + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package org.linphone.p2pproxy.core.sipproxy; + +import org.linphone.p2pproxy.api.P2pProxyException; +import org.zoolu.sip.message.Message; +import org.zoolu.sip.provider.SipProvider; + +public interface SipProxy { + public void proxyRequest(SipProvider aProvider, Message aMessage) throws P2pProxyException; + public void proxyResponse(SipProvider aProvider, Message aMessage) throws P2pProxyException; +} diff --git a/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipProxyRegistrar.java b/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipProxyRegistrar.java index 286ebcb1f..03d8ef628 100644 --- a/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipProxyRegistrar.java +++ b/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipProxyRegistrar.java @@ -65,7 +65,7 @@ import org.zoolu.sip.provider.SipProvider; import org.zoolu.sip.provider.SipProviderListener; import org.zoolu.sip.provider.SipStack; import org.zoolu.sip.transaction.TransactionServer; -public class SipProxyRegistrar implements SipProviderListener,PipeMsgListener,SipProxyRegistrarMBean { +public class SipProxyRegistrar implements SipProviderListener,SipProxyRegistrarMBean { private final static Logger mLog = Logger.getLogger(SipProxyRegistrar.class); public final static String REGISTRAR_PORT="org.linphone.p2pproxy.SipListener.registrar.port"; public final static String UDP_PORT_BEGING="org.linphone.p2pproxy.udp.port.begin"; @@ -81,7 +81,7 @@ public class SipProxyRegistrar implements SipProviderListener,PipeMsgListener,Si private final P2pProxyAccountManagementMBean mP2pProxyAccountManagement; private final Configurator mProperties; - private final SdpProcessor mSdpProcessor; + //private long mNumberOfEstablishedCall; private long mNumberOfRefusedRegistration; private long mNumberOfSuccessfullRegistration; @@ -183,7 +183,7 @@ public class SipProxyRegistrar implements SipProviderListener,PipeMsgListener,Si mProvider=new SipProvider(null,lPort,lProto,SipProvider.ALL_INTERFACES); mProvider.addSipProviderListener(SipProvider.PROMISQUE,this); mPool = Executors.newCachedThreadPool(); - mSdpProcessor = new SdpProcessorImpl(aP2pProxyRtpRelayManagement); + } public synchronized void onReceivedMessage(SipProvider aProvider, Message aMessage) { @@ -289,61 +289,6 @@ public class SipProxyRegistrar implements SipProviderListener,PipeMsgListener,Si aRegistration.NetResources.publish(aRegistration.Expiration); } -////////////////////////////////////////////////////////////////////// -////jxta service methods -///////////////////////////////////////////////////////////////////// - - - public void pipeMsgEvent(PipeMsgEvent anEvent) { - MessageElement lMessageElement = anEvent.getMessage().getMessageElement("SIP"); - if (lMessageElement == null) { - //nop, this is not for me - return; - } - String lMesssage = lMessageElement.toString(); - mLog.info("pipe event sip message["+lMesssage+"]"); - Message lSipMessage = new Message(lMesssage); - // process request - if (lSipMessage.isRequest()) { - SipURL lNextHope ; - // get next hope from registrar - String lToName = lSipMessage.getToHeader().getNameAddress().getAddress().toString(); - if (mRegistrationTab.containsKey(lToName)) { - lNextHope = new SipURL(mRegistrationTab.get(lToName).Contact); - } else { - mLog.error("user ["+lToName+"] not found"); - return; - } - //RequestLine lRequestLine = new RequestLine(lSipMessage.getRequestLine().getMethod(),lNextHope); - //lSipMessage.setRequestLine(lRequestLine); - MultipleHeader lMultipleRoute = lSipMessage.getRoutes(); - RouteHeader lRouteHeader = new RouteHeader(new NameAddress(lNextHope+";lr")); - //lRouteHeader.setParameter("lr", null); - if (lMultipleRoute != null) { - lMultipleRoute.addTop(lRouteHeader); - lSipMessage.setRoutes(lMultipleRoute); - } else { - lSipMessage.addRouteHeader(lRouteHeader); - } - // add Via only udp - SipUtils.addVia(mProvider,lSipMessage); - // add recordRoute - SipUtils.addRecordRoute(mProvider,lSipMessage); - - } else { - //response - //1 remove via header - SipUtils.removeVia(mProvider,lSipMessage); - } - try { - mSdpProcessor.processSdpBeforeSendingToSipUA( lSipMessage); - } catch (P2pProxyException e) { - mLog.error("enable to re-write sdp",e); - } - - mProvider.sendMessage(lSipMessage); - // - } diff --git a/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipUtils.java b/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipUtils.java new file mode 100644 index 000000000..666612239 --- /dev/null +++ b/p2pproxy/src/org/linphone/p2pproxy/core/sipproxy/SipUtils.java @@ -0,0 +1,52 @@ +/* +p2pproxy Copyright (C) 2007 Jehan Monnier () + +SipUtils.java - . + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package org.linphone.p2pproxy.core.sipproxy; + +import org.zoolu.sip.address.NameAddress; +import org.zoolu.sip.address.SipURL; +import org.zoolu.sip.header.Header; +import org.zoolu.sip.header.RecordRouteHeader; +import org.zoolu.sip.header.ViaHeader; +import org.zoolu.sip.message.Message; +import org.zoolu.sip.provider.SipProvider; + +public class SipUtils { + public static void addVia(SipProvider aProvider, Message aMessage) { + ViaHeader via=new ViaHeader("udp",aProvider.getViaAddress(),aProvider.getPort()); + String branch=aProvider.pickBranch(aMessage); + via.setBranch(branch); + aMessage.addViaHeader(via); + } + public static void addRecordRoute(SipProvider aProvider, Message aMessage) { + SipURL lRecordRoute; + lRecordRoute=new SipURL(aProvider.getViaAddress(),aProvider.getPort()); + lRecordRoute.addLr(); + RecordRouteHeader lRecordRouteHeader=new RecordRouteHeader(new NameAddress(lRecordRoute)); + aMessage.addRecordRouteHeader(lRecordRouteHeader); + } + public static void removeVia(SipProvider aProvider, Message aMessage) { + synchronized (aMessage) { + ViaHeader lViaHeader =new ViaHeader((Header)aMessage.getVias().getHeaders().elementAt(0)); + if (lViaHeader.getHost().equals(aProvider.getViaAddress()) && lViaHeader.getPort() == aProvider.getPort() ) { + aMessage.removeViaHeader(); + } + } + } +}