[sip-comm-dev] Re: [Fmj-devel] FMJ uses the remote (target) port number to open a local socket (port)


#1

Does my patch solve the issue for you? Thanks, Ken.

Werner Dittmann wrote:

···

Maybe true - however IP based protocols may also be used on the same
system (locally) thus you may have applications on the same computer
that use RTP to communicate, also it's convenient for testing.

Even if it is an address of another system then the port number belongs
to the other system, and not to the own system. Thus it is an error to
open this port number on the local system because it may be allocated to
yet another application.

With respect to JMF: the snippet below is a code snippet from a working
JMF application. I have two RTP programs (clients) that communicate using
RTP that work using JMF.

The different behavour is:

The first client opens port number 5002 to receive data from the second client.
The second client opens port number 5004 to receive data from the first client.

When I start the first client it opens port number 5002 _and_ port number 5004,
thus the second client cannot open it's receiving port and fails during
initialization.

The offending code is placed in RTPSessionMgr.addTarget(...) that creates
a RTPSocketAdapter:

RTPSocketAdapter socket = new RTPSocketAdapter(
         localAddress.getDataAddress(),
         remoteAddress.getDataAddress(), remoteAddress.getDataPort(),
         remoteAddress.getTimeToLive());

This in turn uses the following constructor:

     /**
      * Creates a new RTPSocketAdaptor
      * @param laddr The local address to bind to
      * @param addr The address of the socket
      * @param port The port of the socket
      * @param ttl The ttl for sending data
      * @throws IOException I/O Exception
      */
     public RTPSocketAdapter(InetAddress laddr, InetAddress addr, int port,
             int ttl)
             throws IOException {
         try {

             // If the address is multicast, create multicast sockets and joing
             // groups etc
             if (addr.isMulticastAddress()) {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
                 //((MulticastSocket) dataSock).setInterface(laddr);
                 ((MulticastSocket) dataSock).joinGroup(addr);
                 ((MulticastSocket) dataSock).setTimeToLive(ttl);
                 ((MulticastSocket) dataSock).setLoopbackMode(false);
                 //((MulticastSocket) ctrlSock).setInterface(laddr);
                 ((MulticastSocket) ctrlSock).joinGroup(addr);
                 ((MulticastSocket) ctrlSock).setTimeToLive(ttl);
                 ((MulticastSocket) ctrlSock).setLoopbackMode(false);
             }

             // If the address is unicast, create unicast sockets
             else {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
             }
         } catch (SocketException e) {
             throw new IOException(e.getMessage());
         }

         // Set the address and port
         this.addr = addr; // this is _not_ the local address
         this.port = port; // this is _not_ the local port #

         // Send out data to open the correct ports
         dataSock.send(new DatagramPacket(new byte[100], 100, addr, port));
         ctrlSock.send(new DatagramPacket(new byte[100], 100, addr, port + 1));
     }

This _always_ creates 2 new EncryptedRTPSocket (without encryption) that in turn
open the data and control port on the local system (some comments inserted by me).
The above example shows that the two .send(...) methods send the data via
the port that was set via addTarget (addTarget defines a receiving address and an
receiving port number of some system). In addition: sending arbitrary data just
"to open a port" is not good practice - the receiver may not know what to do with
it.

A correct implementation would be: save the taraget address and port number (maybe
in a vector) and use it as follows when sending a RTP datagram to the other client
(as an example here):

   localUDPsocket.send(new DatagramPacket(data, 0, data.length, remoteAddr, remotePort));

An UDP application sends a datagram packet using its local UDP socket. The datagram
packet contains the data as well as the remote address and remote port.

Regards,
Werner

Ken Larson schrieb:
  

Why do you use the same address for sa and target? My understanding is that sa would normally be localhost and that target would normally be a remote address?

Perhaps you could send a complete example, and a description of how the behavior differs from JMF (run it both ways, run nmap to show the open ports).

Vielen dank,

Ken

Werner Dittmann wrote:
    

A few days ago I downloaded a CVS version of FMJ to build test programs,
a RTP client and a RTP Server that already work using JMF. Trying to do the
same with FMJ resulted in problems. Here the code snippet how I created
the RTPManager and initialize it:

...
SessionAddress sa = new SessionAddress(ia, 5002);
SessionAddress target = new SessionAddress(ia, 5004);
try {

     mgr = RTPManager.newInstance();

     mgr.initialize(sa);

     mgr.addSessionListener(this);
     mgr.addReceiveStreamListener(this);

     mgr.addTarget(target);
} catch (Exception e) {
     System.err.println("Cannot create the RTP Session: " + e.getMessage());
}

...

This is the normal way to setup RTP and add a target. Well, FMJ also opens the
*target port* number on the *local* system - which is wrong because this is a port
on the *remote system* that may not be available on the local system.
This behaviour may cause spurious problems on the local system. The problem is
located in FMJ's classes RTPSocketAdapter and EncryptedRTPSocket.

FMJ must open the port number of the session address given in initialize(...) only.
The target address is written into the DatagramPacket only and this DatagramPacket
is sent using the open port given during initialize(...).

Hope this finding helps to fix this in FMJ.

Regards,
Werner

PS: when using an own connector, mgr.initialize() is called with the connector
and setting the target at this connector works well - communication was established
(tested with my modifed and bug fixed SRTP connector). This also proves that the
connector implementation of FMJ's RTPSocketAdapter is buggy.

Werner

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Fmj-devel mailing list
Fmj-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/fmj-devel

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Fmj-devel mailing list
Fmj-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/fmj-devel


#2

Ken,

do you refer to the patch you sent to the mailing list yesterday?
If so then this patch does not solve the problem. It still opens
the ports that were set using "addTarget". The check isRTP() just checks
if it is an even or odd portnumber (RTP data or control port according to
rfc3550). As said the portnumber given to addTarget shall never be
opened on the local system. If you look at the usual use case in
SIP clients:

a SIP client determines which RTP ports (data/control) are available
at its system. The client opens these sockets for read/write and using
SIP/SDP it sends this information to the other client. This client in
turn determines which port numbers are available to it, opens these
sockets. Using addTarget() this second client adds the address and port
number to the RTP stack and can now send data to the other party. At
the same time it sends back its address/port information to the first
client. As said the port number received via SIP/SDP belongs to the
"remote" system and the "local" system shall not open it because it
may be used otherwise.

The current implementation uses the Encrypted sockets as underlying
socket framework. If FMJ is going to implement RTP encryption as defined
in rfc3550 then this encrypted socket framework shall be adapted or
used in another way to fix the "open socket" problem.

I'll have a look into the multicast issue and give some feedback later.

Regards,
Werner

Ken Larson schrieb:

Does my patch solve the issue for you? Thanks, Ken.

Werner Dittmann wrote:

Maybe true - however IP based protocols may also be used on the same
system (locally) thus you may have applications on the same computer
that use RTP to communicate, also it's convenient for testing.

Even if it is an address of another system then the port number belongs
to the other system, and not to the own system. Thus it is an error to
open this port number on the local system because it may be allocated to
yet another application.

With respect to JMF: the snippet below is a code snippet from a working
JMF application. I have two RTP programs (clients) that communicate
using
RTP that work using JMF.

The different behavour is:

The first client opens port number 5002 to receive data from the
second client.
The second client opens port number 5004 to receive data from the
first client.

When I start the first client it opens port number 5002 _and_ port
number 5004,
thus the second client cannot open it's receiving port and fails during
initialization.

The offending code is placed in RTPSessionMgr.addTarget(...) that creates
a RTPSocketAdapter:

RTPSocketAdapter socket = new RTPSocketAdapter(
         localAddress.getDataAddress(),
         remoteAddress.getDataAddress(), remoteAddress.getDataPort(),
         remoteAddress.getTimeToLive());

This in turn uses the following constructor:

     /**
      * Creates a new RTPSocketAdaptor
      * @param laddr The local address to bind to
      * @param addr The address of the socket
      * @param port The port of the socket
      * @param ttl The ttl for sending data
      * @throws IOException I/O Exception
      */
     public RTPSocketAdapter(InetAddress laddr, InetAddress addr, int
port,
             int ttl)
             throws IOException {
         try {

             // If the address is multicast, create multicast sockets
and joing
             // groups etc
             if (addr.isMulticastAddress()) {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
                 //((MulticastSocket) dataSock).setInterface(laddr);
                 ((MulticastSocket) dataSock).joinGroup(addr);
                 ((MulticastSocket) dataSock).setTimeToLive(ttl);
                 ((MulticastSocket) dataSock).setLoopbackMode(false);
                 //((MulticastSocket) ctrlSock).setInterface(laddr);
                 ((MulticastSocket) ctrlSock).joinGroup(addr);
                 ((MulticastSocket) ctrlSock).setTimeToLive(ttl);
                 ((MulticastSocket) ctrlSock).setLoopbackMode(false);
             }

             // If the address is unicast, create unicast sockets
             else {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
             }
         } catch (SocketException e) {
             throw new IOException(e.getMessage());
         }

         // Set the address and port
         this.addr = addr; // this is _not_ the local address
         this.port = port; // this is _not_ the local port #

         // Send out data to open the correct ports
         dataSock.send(new DatagramPacket(new byte[100], 100, addr,
port));
         ctrlSock.send(new DatagramPacket(new byte[100], 100, addr,
port + 1));
     }

This _always_ creates 2 new EncryptedRTPSocket (without encryption)
that in turn
open the data and control port on the local system (some comments
inserted by me).
The above example shows that the two .send(...) methods send the data via
the port that was set via addTarget (addTarget defines a receiving
address and an
receiving port number of some system). In addition: sending arbitrary
data just
"to open a port" is not good practice - the receiver may not know what
to do with
it.

<SNIP ---- SNAP>

···

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Fmj-devel mailing list
Fmj-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/fmj-devel


#3

my intention with that patch was to use the constructor to the socket which does not specify the port, thereby opening a random (available) port. It should no longer open the actual port specified on the local system. Am I missing something?

Perhaps you could propose a patch to FMJ? That would be very helpful.

Ken

Werner Dittmann wrote:

···

Ken,

do you refer to the patch you sent to the mailing list yesterday?
If so then this patch does not solve the problem. It still opens
the ports that were set using "addTarget". The check isRTP() just checks
if it is an even or odd portnumber (RTP data or control port according to
rfc3550). As said the portnumber given to addTarget shall never be
opened on the local system. If you look at the usual use case in
SIP clients:

a SIP client determines which RTP ports (data/control) are available
at its system. The client opens these sockets for read/write and using
SIP/SDP it sends this information to the other client. This client in
turn determines which port numbers are available to it, opens these
sockets. Using addTarget() this second client adds the address and port
number to the RTP stack and can now send data to the other party. At
the same time it sends back its address/port information to the first
client. As said the port number received via SIP/SDP belongs to the
"remote" system and the "local" system shall not open it because it
may be used otherwise.

The current implementation uses the Encrypted sockets as underlying
socket framework. If FMJ is going to implement RTP encryption as defined
in rfc3550 then this encrypted socket framework shall be adapted or
used in another way to fix the "open socket" problem.

I'll have a look into the multicast issue and give some feedback later.

Regards,
Werner

Ken Larson schrieb:

Does my patch solve the issue for you? Thanks, Ken.

Werner Dittmann wrote:

Maybe true - however IP based protocols may also be used on the same
system (locally) thus you may have applications on the same computer
that use RTP to communicate, also it's convenient for testing.

Even if it is an address of another system then the port number belongs
to the other system, and not to the own system. Thus it is an error to
open this port number on the local system because it may be allocated to
yet another application.

With respect to JMF: the snippet below is a code snippet from a working
JMF application. I have two RTP programs (clients) that communicate using
RTP that work using JMF.

The different behavour is:

The first client opens port number 5002 to receive data from the second client.
The second client opens port number 5004 to receive data from the first client.

When I start the first client it opens port number 5002 _and_ port number 5004,
thus the second client cannot open it's receiving port and fails during
initialization.

The offending code is placed in RTPSessionMgr.addTarget(...) that creates
a RTPSocketAdapter:

RTPSocketAdapter socket = new RTPSocketAdapter(
         localAddress.getDataAddress(),
         remoteAddress.getDataAddress(), remoteAddress.getDataPort(),
         remoteAddress.getTimeToLive());

This in turn uses the following constructor:

     /**
      * Creates a new RTPSocketAdaptor
      * @param laddr The local address to bind to
      * @param addr The address of the socket
      * @param port The port of the socket
      * @param ttl The ttl for sending data
      * @throws IOException I/O Exception
      */
     public RTPSocketAdapter(InetAddress laddr, InetAddress addr, int port,
             int ttl)
             throws IOException {
         try {

             // If the address is multicast, create multicast sockets and joing
             // groups etc
             if (addr.isMulticastAddress()) {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
                 //((MulticastSocket) dataSock).setInterface(laddr);
                 ((MulticastSocket) dataSock).joinGroup(addr);
                 ((MulticastSocket) dataSock).setTimeToLive(ttl);
                 ((MulticastSocket) dataSock).setLoopbackMode(false);
                 //((MulticastSocket) ctrlSock).setInterface(laddr);
                 ((MulticastSocket) ctrlSock).joinGroup(addr);
                 ((MulticastSocket) ctrlSock).setTimeToLive(ttl);
                 ((MulticastSocket) ctrlSock).setLoopbackMode(false);
             }

             // If the address is unicast, create unicast sockets
             else {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
             }
         } catch (SocketException e) {
             throw new IOException(e.getMessage());
         }

         // Set the address and port
         this.addr = addr; // this is _not_ the local address
         this.port = port; // this is _not_ the local port #

         // Send out data to open the correct ports
         dataSock.send(new DatagramPacket(new byte[100], 100, addr, port));
         ctrlSock.send(new DatagramPacket(new byte[100], 100, addr, port + 1));
     }

This _always_ creates 2 new EncryptedRTPSocket (without encryption) that in turn
open the data and control port on the local system (some comments inserted by me).
The above example shows that the two .send(...) methods send the data via
the port that was set via addTarget (addTarget defines a receiving address and an
receiving port number of some system). In addition: sending arbitrary data just
"to open a port" is not good practice - the receiver may not know what to do with
it.

<SNIP ---- SNAP>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#4

yes, this tries to open a random port - however to send RTP data
FMJ shall use the same port as it uses to receive data (symmetrical
RTP) to avoid all sort problems with firewalls, media gateways (in
particualr Border Gateway Controllers) and some other "nasty" stuff :slight_smile:

I'll have a deeper look at this an propose a patch - this may take
some time, hopefully I can do it during the next weekend.

Regards,
Werner

Ken Larson schrieb:

···

my intention with that patch was to use the constructor to the socket which does not specify the port, thereby opening a random (available) port. It should no longer open the actual port specified on the local system. Am I missing something?

Perhaps you could propose a patch to FMJ? That would be very helpful.

Ken

Werner Dittmann wrote:

Ken,

do you refer to the patch you sent to the mailing list yesterday?
If so then this patch does not solve the problem. It still opens
the ports that were set using "addTarget". The check isRTP() just checks
if it is an even or odd portnumber (RTP data or control port according to
rfc3550). As said the portnumber given to addTarget shall never be
opened on the local system. If you look at the usual use case in
SIP clients:

a SIP client determines which RTP ports (data/control) are available
at its system. The client opens these sockets for read/write and using
SIP/SDP it sends this information to the other client. This client in
turn determines which port numbers are available to it, opens these
sockets. Using addTarget() this second client adds the address and port
number to the RTP stack and can now send data to the other party. At
the same time it sends back its address/port information to the first
client. As said the port number received via SIP/SDP belongs to the
"remote" system and the "local" system shall not open it because it
may be used otherwise.

The current implementation uses the Encrypted sockets as underlying
socket framework. If FMJ is going to implement RTP encryption as defined
in rfc3550 then this encrypted socket framework shall be adapted or
used in another way to fix the "open socket" problem.

I'll have a look into the multicast issue and give some feedback later.

Regards,
Werner

Ken Larson schrieb:

Does my patch solve the issue for you? Thanks, Ken.

Werner Dittmann wrote:

Maybe true - however IP based protocols may also be used on the same
system (locally) thus you may have applications on the same computer
that use RTP to communicate, also it's convenient for testing.

Even if it is an address of another system then the port number belongs
to the other system, and not to the own system. Thus it is an error to
open this port number on the local system because it may be allocated to
yet another application.

With respect to JMF: the snippet below is a code snippet from a working
JMF application. I have two RTP programs (clients) that communicate using
RTP that work using JMF.

The different behavour is:

The first client opens port number 5002 to receive data from the second client.
The second client opens port number 5004 to receive data from the first client.

When I start the first client it opens port number 5002 _and_ port number 5004,
thus the second client cannot open it's receiving port and fails during
initialization.

The offending code is placed in RTPSessionMgr.addTarget(...) that creates
a RTPSocketAdapter:

RTPSocketAdapter socket = new RTPSocketAdapter(
         localAddress.getDataAddress(),
         remoteAddress.getDataAddress(), remoteAddress.getDataPort(),
         remoteAddress.getTimeToLive());

This in turn uses the following constructor:

     /**
      * Creates a new RTPSocketAdaptor
      * @param laddr The local address to bind to
      * @param addr The address of the socket
      * @param port The port of the socket
      * @param ttl The ttl for sending data
      * @throws IOException I/O Exception
      */
     public RTPSocketAdapter(InetAddress laddr, InetAddress addr, int port,
             int ttl)
             throws IOException {
         try {

             // If the address is multicast, create multicast sockets and joing
             // groups etc
             if (addr.isMulticastAddress()) {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
                 //((MulticastSocket) dataSock).setInterface(laddr);
                 ((MulticastSocket) dataSock).joinGroup(addr);
                 ((MulticastSocket) dataSock).setTimeToLive(ttl);
                 ((MulticastSocket) dataSock).setLoopbackMode(false);
                 //((MulticastSocket) ctrlSock).setInterface(laddr);
                 ((MulticastSocket) ctrlSock).joinGroup(addr);
                 ((MulticastSocket) ctrlSock).setTimeToLive(ttl);
                 ((MulticastSocket) ctrlSock).setLoopbackMode(false);
             }

             // If the address is unicast, create unicast sockets
             else {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
             }
         } catch (SocketException e) {
             throw new IOException(e.getMessage());
         }

         // Set the address and port
         this.addr = addr; // this is _not_ the local address
         this.port = port; // this is _not_ the local port #

         // Send out data to open the correct ports
         dataSock.send(new DatagramPacket(new byte[100], 100, addr, port));
         ctrlSock.send(new DatagramPacket(new byte[100], 100, addr, port + 1));
     }

This _always_ creates 2 new EncryptedRTPSocket (without encryption) that in turn
open the data and control port on the local system (some comments inserted by me).
The above example shows that the two .send(...) methods send the data via
the port that was set via addTarget (addTarget defines a receiving address and an
receiving port number of some system). In addition: sending arbitrary data just
"to open a port" is not good practice - the receiver may not know what to do with
it.

<SNIP ---- SNAP>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#5

Hey folks,

Couldn't chime in on this one earlier (was a bit flooded lately). I just
wanted to mention that this is very important for us in SIP Communicator
and we heavily rely on such behaviour from JMF. In other words we expect
an RTPManager to use only one local socket (and hence port) for both
sending and receiving traffic associated with that manager.

We also currently rely on the fact that this would be the port indicated
in the SessionAddress that we pass to the manager in the initialize
method, as this way we can configure SC to use ports from specific range
which is important in case we want it to work behind a firewall that's
doing port forwarding for that range.

I was therefore thinking that in case Werner doesn't find the time to
come up with a patch, then Martin you might want to have a look at it
(provided this doesn't disrupt the GSoC schedule you have defined with
Ken of course). Ken, what do you think?

Cheers
Emil

Werner Dittmann написа:

···

yes, this tries to open a random port - however to send RTP data
FMJ shall use the same port as it uses to receive data (symmetrical
RTP) to avoid all sort problems with firewalls, media gateways (in
particualr Border Gateway Controllers) and some other "nasty" stuff :slight_smile:

I'll have a deeper look at this an propose a patch - this may take
some time, hopefully I can do it during the next weekend.

Regards,
Werner

Ken Larson schrieb:

my intention with that patch was to use the constructor to the socket
which does not specify the port, thereby opening a random (available)
port. It should no longer open the actual port specified on the local
system. Am I missing something?

Perhaps you could propose a patch to FMJ? That would be very helpful.

Ken

Werner Dittmann wrote:

Ken,

do you refer to the patch you sent to the mailing list yesterday?
If so then this patch does not solve the problem. It still opens
the ports that were set using "addTarget". The check isRTP() just checks
if it is an even or odd portnumber (RTP data or control port according to
rfc3550). As said the portnumber given to addTarget shall never be
opened on the local system. If you look at the usual use case in
SIP clients:

a SIP client determines which RTP ports (data/control) are available
at its system. The client opens these sockets for read/write and using
SIP/SDP it sends this information to the other client. This client in
turn determines which port numbers are available to it, opens these
sockets. Using addTarget() this second client adds the address and port
number to the RTP stack and can now send data to the other party. At
the same time it sends back its address/port information to the first
client. As said the port number received via SIP/SDP belongs to the
"remote" system and the "local" system shall not open it because it
may be used otherwise.

The current implementation uses the Encrypted sockets as underlying
socket framework. If FMJ is going to implement RTP encryption as defined
in rfc3550 then this encrypted socket framework shall be adapted or
used in another way to fix the "open socket" problem.

I'll have a look into the multicast issue and give some feedback later.

Regards,
Werner

Ken Larson schrieb:

Does my patch solve the issue for you? Thanks, Ken.

Werner Dittmann wrote:

Maybe true - however IP based protocols may also be used on the same
system (locally) thus you may have applications on the same computer
that use RTP to communicate, also it's convenient for testing.

Even if it is an address of another system then the port number belongs
to the other system, and not to the own system. Thus it is an error to
open this port number on the local system because it may be
allocated to
yet another application.

With respect to JMF: the snippet below is a code snippet from a working
JMF application. I have two RTP programs (clients) that communicate
using
RTP that work using JMF.

The different behavour is:

The first client opens port number 5002 to receive data from the
second client.
The second client opens port number 5004 to receive data from the
first client.

When I start the first client it opens port number 5002 _and_ port
number 5004,
thus the second client cannot open it's receiving port and fails during
initialization.

The offending code is placed in RTPSessionMgr.addTarget(...) that
creates
a RTPSocketAdapter:

RTPSocketAdapter socket = new RTPSocketAdapter(
         localAddress.getDataAddress(),
         remoteAddress.getDataAddress(), remoteAddress.getDataPort(),
         remoteAddress.getTimeToLive());

This in turn uses the following constructor:

     /**
      * Creates a new RTPSocketAdaptor
      * @param laddr The local address to bind to
      * @param addr The address of the socket
      * @param port The port of the socket
      * @param ttl The ttl for sending data
      * @throws IOException I/O Exception
      */
     public RTPSocketAdapter(InetAddress laddr, InetAddress addr,
int port,
             int ttl)
             throws IOException {
         try {

             // If the address is multicast, create multicast
sockets and joing
             // groups etc
             if (addr.isMulticastAddress()) {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
                 //((MulticastSocket) dataSock).setInterface(laddr);
                 ((MulticastSocket) dataSock).joinGroup(addr);
                 ((MulticastSocket) dataSock).setTimeToLive(ttl);
                 ((MulticastSocket) dataSock).setLoopbackMode(false);
                 //((MulticastSocket) ctrlSock).setInterface(laddr);
                 ((MulticastSocket) ctrlSock).joinGroup(addr);
                 ((MulticastSocket) ctrlSock).setTimeToLive(ttl);
                 ((MulticastSocket) ctrlSock).setLoopbackMode(false);
             }

             // If the address is unicast, create unicast sockets
             else {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
             }
         } catch (SocketException e) {
             throw new IOException(e.getMessage());
         }

         // Set the address and port
         this.addr = addr; // this is _not_ the local address
         this.port = port; // this is _not_ the local port #

         // Send out data to open the correct ports
         dataSock.send(new DatagramPacket(new byte[100], 100, addr,
port));
         ctrlSock.send(new DatagramPacket(new byte[100], 100, addr,
port + 1));
     }

This _always_ creates 2 new EncryptedRTPSocket (without encryption)
that in turn
open the data and control port on the local system (some comments
inserted by me).
The above example shows that the two .send(...) methods send the
data via
the port that was set via addTarget (addTarget defines a receiving
address and an
receiving port number of some system). In addition: sending
arbitrary data just
"to open a port" is not good practice - the receiver may not know
what to do with
it.

<SNIP ---- SNAP>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#6

Hi Emil,
Yes I might take a look at it.. I am currently working on making the GSM
codec work, but that will not (hopefully) take much longer. After that I
will take a look at this issue.

···

On Sat, Jun 14, 2008 at 7:11 PM, Emil Ivov <emcho@sip-communicator.org> wrote:

Hey folks,

Couldn't chime in on this one earlier (was a bit flooded lately). I just
wanted to mention that this is very important for us in SIP Communicator
and we heavily rely on such behaviour from JMF. In other words we expect
an RTPManager to use only one local socket (and hence port) for both
sending and receiving traffic associated with that manager.

We also currently rely on the fact that this would be the port indicated
in the SessionAddress that we pass to the manager in the initialize
method, as this way we can configure SC to use ports from specific range
which is important in case we want it to work behind a firewall that's
doing port forwarding for that range.

I was therefore thinking that in case Werner doesn't find the time to
come up with a patch, then Martin you might want to have a look at it
(provided this doesn't disrupt the GSoC schedule you have defined with
Ken of course). Ken, what do you think?

Cheers
Emil

Werner Dittmann написа:
> yes, this tries to open a random port - however to send RTP data
> FMJ shall use the same port as it uses to receive data (symmetrical
> RTP) to avoid all sort problems with firewalls, media gateways (in
> particualr Border Gateway Controllers) and some other "nasty" stuff :slight_smile:
>
> I'll have a deeper look at this an propose a patch - this may take
> some time, hopefully I can do it during the next weekend.
>
> Regards,
> Werner
>
> Ken Larson schrieb:
>> my intention with that patch was to use the constructor to the socket
>> which does not specify the port, thereby opening a random (available)
>> port. It should no longer open the actual port specified on the local
>> system. Am I missing something?
>>
>> Perhaps you could propose a patch to FMJ? That would be very helpful.
>>
>> Ken
>>
>> Werner Dittmann wrote:
>>> Ken,
>>>
>>> do you refer to the patch you sent to the mailing list yesterday?
>>> If so then this patch does not solve the problem. It still opens
>>> the ports that were set using "addTarget". The check isRTP() just
checks
>>> if it is an even or odd portnumber (RTP data or control port according
to
>>> rfc3550). As said the portnumber given to addTarget shall never be
>>> opened on the local system. If you look at the usual use case in
>>> SIP clients:
>>>
>>> a SIP client determines which RTP ports (data/control) are available
>>> at its system. The client opens these sockets for read/write and using
>>> SIP/SDP it sends this information to the other client. This client in
>>> turn determines which port numbers are available to it, opens these
>>> sockets. Using addTarget() this second client adds the address and port
>>> number to the RTP stack and can now send data to the other party. At
>>> the same time it sends back its address/port information to the first
>>> client. As said the port number received via SIP/SDP belongs to the
>>> "remote" system and the "local" system shall not open it because it
>>> may be used otherwise.
>>>
>>> The current implementation uses the Encrypted sockets as underlying
>>> socket framework. If FMJ is going to implement RTP encryption as
defined
>>> in rfc3550 then this encrypted socket framework shall be adapted or
>>> used in another way to fix the "open socket" problem.
>>>
>>> I'll have a look into the multicast issue and give some feedback later.
>>>
>>> Regards,
>>> Werner
>>>
>>> Ken Larson schrieb:
>>>> Does my patch solve the issue for you? Thanks, Ken.
>>>>
>>>> Werner Dittmann wrote:
>>>>> Maybe true - however IP based protocols may also be used on the same
>>>>> system (locally) thus you may have applications on the same computer
>>>>> that use RTP to communicate, also it's convenient for testing.
>>>>>
>>>>> Even if it is an address of another system then the port number
belongs
>>>>> to the other system, and not to the own system. Thus it is an error
to
>>>>> open this port number on the local system because it may be
>>>>> allocated to
>>>>> yet another application.
>>>>>
>>>>> With respect to JMF: the snippet below is a code snippet from a
working
>>>>> JMF application. I have two RTP programs (clients) that communicate
>>>>> using
>>>>> RTP that work using JMF.
>>>>>
>>>>> The different behavour is:
>>>>>
>>>>> The first client opens port number 5002 to receive data from the
>>>>> second client.
>>>>> The second client opens port number 5004 to receive data from the
>>>>> first client.
>>>>>
>>>>> When I start the first client it opens port number 5002 _and_ port
>>>>> number 5004,
>>>>> thus the second client cannot open it's receiving port and fails
during
>>>>> initialization.
>>>>>
>>>>> The offending code is placed in RTPSessionMgr.addTarget(...) that
>>>>> creates
>>>>> a RTPSocketAdapter:
>>>>>
>>>>> RTPSocketAdapter socket = new RTPSocketAdapter(
>>>>> localAddress.getDataAddress(),
>>>>> remoteAddress.getDataAddress(), remoteAddress.getDataPort(),
>>>>> remoteAddress.getTimeToLive());
>>>>>
>>>>> This in turn uses the following constructor:
>>>>>
>>>>> /**
>>>>> * Creates a new RTPSocketAdaptor
>>>>> * @param laddr The local address to bind to
>>>>> * @param addr The address of the socket
>>>>> * @param port The port of the socket
>>>>> * @param ttl The ttl for sending data
>>>>> * @throws IOException I/O Exception
>>>>> */
>>>>> public RTPSocketAdapter(InetAddress laddr, InetAddress addr,
>>>>> int port,
>>>>> int ttl)
>>>>> throws IOException {
>>>>> try {
>>>>>
>>>>> // If the address is multicast, create multicast
>>>>> sockets and joing
>>>>> // groups etc
>>>>> if (addr.isMulticastAddress()) {
>>>>> dataSock = new EncryptedRTPSocket(null, port);
>>>>> ctrlSock = new EncryptedRTPSocket(null, port + 1);
>>>>> //((MulticastSocket) dataSock).setInterface(laddr);
>>>>> ((MulticastSocket) dataSock).joinGroup(addr);
>>>>> ((MulticastSocket) dataSock).setTimeToLive(ttl);
>>>>> ((MulticastSocket) dataSock).setLoopbackMode(false);
>>>>> //((MulticastSocket) ctrlSock).setInterface(laddr);
>>>>> ((MulticastSocket) ctrlSock).joinGroup(addr);
>>>>> ((MulticastSocket) ctrlSock).setTimeToLive(ttl);
>>>>> ((MulticastSocket) ctrlSock).setLoopbackMode(false);
>>>>> }
>>>>>
>>>>> // If the address is unicast, create unicast sockets
>>>>> else {
>>>>> dataSock = new EncryptedRTPSocket(null, port);
>>>>> ctrlSock = new EncryptedRTPSocket(null, port + 1);
>>>>> }
>>>>> } catch (SocketException e) {
>>>>> throw new IOException(e.getMessage());
>>>>> }
>>>>>
>>>>> // Set the address and port
>>>>> this.addr = addr; // this is _not_ the local address
>>>>> this.port = port; // this is _not_ the local port #
>>>>>
>>>>> // Send out data to open the correct ports
>>>>> dataSock.send(new DatagramPacket(new byte[100], 100, addr,
>>>>> port));
>>>>> ctrlSock.send(new DatagramPacket(new byte[100], 100, addr,
>>>>> port + 1));
>>>>> }
>>>>>
>>>>> This _always_ creates 2 new EncryptedRTPSocket (without encryption)
>>>>> that in turn
>>>>> open the data and control port on the local system (some comments
>>>>> inserted by me).
>>>>> The above example shows that the two .send(...) methods send the
>>>>> data via
>>>>> the port that was set via addTarget (addTarget defines a receiving
>>>>> address and an
>>>>> receiving port number of some system). In addition: sending
>>>>> arbitrary data just
>>>>> "to open a port" is not good practice - the receiver may not know
>>>>> what to do with
>>>>> it.
>>>>>
>>> <SNIP ---- SNAP>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
>>> For additional commands, e-mail:
dev-help@sip-communicator.dev.java.net
>>>
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
>> For additional commands, e-mail: dev-help@sip-communicator.dev.java.net
>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
> For additional commands, e-mail: dev-help@sip-communicator.dev.java.net
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

--
George Carlin - "Frisbeetarianism is the belief that when you die, your
soul goes up on the roof and gets stu...


#7

Hey Martin,

Sure, take your time.

Cheers
Emil

Martin Harvan написа:

···

Hi Emil,
Yes I might take a look at it.. I am currently working on making the GSM
codec work, but that will not (hopefully) take much longer. After that I
will take a look at this issue.

On Sat, Jun 14, 2008 at 7:11 PM, Emil Ivov <emcho@sip-communicator.org > <mailto:emcho@sip-communicator.org>> wrote:

    Hey folks,

    Couldn't chime in on this one earlier (was a bit flooded lately). I just
    wanted to mention that this is very important for us in SIP Communicator
    and we heavily rely on such behaviour from JMF. In other words we expect
    an RTPManager to use only one local socket (and hence port) for both
    sending and receiving traffic associated with that manager.

    We also currently rely on the fact that this would be the port indicated
    in the SessionAddress that we pass to the manager in the initialize
    method, as this way we can configure SC to use ports from specific range
    which is important in case we want it to work behind a firewall that's
    doing port forwarding for that range.

    I was therefore thinking that in case Werner doesn't find the time to
    come up with a patch, then Martin you might want to have a look at it
    (provided this doesn't disrupt the GSoC schedule you have defined with
    Ken of course). Ken, what do you think?

    Cheers
    Emil

    Werner Dittmann написа:
    > yes, this tries to open a random port - however to send RTP data
    > FMJ shall use the same port as it uses to receive data (symmetrical
    > RTP) to avoid all sort problems with firewalls, media gateways (in
    > particualr Border Gateway Controllers) and some other "nasty"
    stuff :slight_smile:
    >
    > I'll have a deeper look at this an propose a patch - this may take
    > some time, hopefully I can do it during the next weekend.
    >
    > Regards,
    > Werner
    >
    > Ken Larson schrieb:
    >> my intention with that patch was to use the constructor to the socket
    >> which does not specify the port, thereby opening a random (available)
    >> port. It should no longer open the actual port specified on the
    local
    >> system. Am I missing something?
    >>
    >> Perhaps you could propose a patch to FMJ? That would be very
    helpful.
    >>
    >> Ken
    >>
    >> Werner Dittmann wrote:
    >>> Ken,
    >>>
    >>> do you refer to the patch you sent to the mailing list yesterday?
    >>> If so then this patch does not solve the problem. It still opens
    >>> the ports that were set using "addTarget". The check isRTP()
    just checks
    >>> if it is an even or odd portnumber (RTP data or control port
    according to
    >>> rfc3550). As said the portnumber given to addTarget shall never be
    >>> opened on the local system. If you look at the usual use case in
    >>> SIP clients:
    >>>
    >>> a SIP client determines which RTP ports (data/control) are available
    >>> at its system. The client opens these sockets for read/write and
    using
    >>> SIP/SDP it sends this information to the other client. This
    client in
    >>> turn determines which port numbers are available to it, opens these
    >>> sockets. Using addTarget() this second client adds the address
    and port
    >>> number to the RTP stack and can now send data to the other party. At
    >>> the same time it sends back its address/port information to the
    first
    >>> client. As said the port number received via SIP/SDP belongs to the
    >>> "remote" system and the "local" system shall not open it because it
    >>> may be used otherwise.
    >>>
    >>> The current implementation uses the Encrypted sockets as underlying
    >>> socket framework. If FMJ is going to implement RTP encryption as
    defined
    >>> in rfc3550 then this encrypted socket framework shall be adapted or
    >>> used in another way to fix the "open socket" problem.
    >>>
    >>> I'll have a look into the multicast issue and give some feedback
    later.
    >>>
    >>> Regards,
    >>> Werner
    >>>
    >>> Ken Larson schrieb:
    >>>> Does my patch solve the issue for you? Thanks, Ken.
    >>>>
    >>>> Werner Dittmann wrote:
    >>>>> Maybe true - however IP based protocols may also be used on
    the same
    >>>>> system (locally) thus you may have applications on the same
    computer
    >>>>> that use RTP to communicate, also it's convenient for testing.
    >>>>>
    >>>>> Even if it is an address of another system then the port
    number belongs
    >>>>> to the other system, and not to the own system. Thus it is an
    error to
    >>>>> open this port number on the local system because it may be
    >>>>> allocated to
    >>>>> yet another application.
    >>>>>
    >>>>> With respect to JMF: the snippet below is a code snippet from
    a working
    >>>>> JMF application. I have two RTP programs (clients) that
    communicate
    >>>>> using
    >>>>> RTP that work using JMF.
    >>>>>
    >>>>> The different behavour is:
    >>>>>
    >>>>> The first client opens port number 5002 to receive data from the
    >>>>> second client.
    >>>>> The second client opens port number 5004 to receive data from the
    >>>>> first client.
    >>>>>
    >>>>> When I start the first client it opens port number 5002 _and_ port
    >>>>> number 5004,
    >>>>> thus the second client cannot open it's receiving port and
    fails during
    >>>>> initialization.
    >>>>>
    >>>>> The offending code is placed in RTPSessionMgr.addTarget(...) that
    >>>>> creates
    >>>>> a RTPSocketAdapter:
    >>>>>
    >>>>> RTPSocketAdapter socket = new RTPSocketAdapter(
    >>>>> localAddress.getDataAddress(),
    >>>>> remoteAddress.getDataAddress(),
    remoteAddress.getDataPort(),
    >>>>> remoteAddress.getTimeToLive());
    >>>>>
    >>>>> This in turn uses the following constructor:
    >>>>>
    >>>>> /**
    >>>>> * Creates a new RTPSocketAdaptor
    >>>>> * @param laddr The local address to bind to
    >>>>> * @param addr The address of the socket
    >>>>> * @param port The port of the socket
    >>>>> * @param ttl The ttl for sending data
    >>>>> * @throws IOException I/O Exception
    >>>>> */
    >>>>> public RTPSocketAdapter(InetAddress laddr, InetAddress addr,
    >>>>> int port,
    >>>>> int ttl)
    >>>>> throws IOException {
    >>>>> try {
    >>>>>
    >>>>> // If the address is multicast, create multicast
    >>>>> sockets and joing
    >>>>> // groups etc
    >>>>> if (addr.isMulticastAddress()) {
    >>>>> dataSock = new EncryptedRTPSocket(null, port);
    >>>>> ctrlSock = new EncryptedRTPSocket(null, port
    + 1);
    >>>>> //((MulticastSocket)
    dataSock).setInterface(laddr);
    >>>>> ((MulticastSocket) dataSock).joinGroup(addr);
    >>>>> ((MulticastSocket) dataSock).setTimeToLive(ttl);
    >>>>> ((MulticastSocket)
    dataSock).setLoopbackMode(false);
    >>>>> //((MulticastSocket)
    ctrlSock).setInterface(laddr);
    >>>>> ((MulticastSocket) ctrlSock).joinGroup(addr);
    >>>>> ((MulticastSocket) ctrlSock).setTimeToLive(ttl);
    >>>>> ((MulticastSocket)
    ctrlSock).setLoopbackMode(false);
    >>>>> }
    >>>>>
    >>>>> // If the address is unicast, create unicast sockets
    >>>>> else {
    >>>>> dataSock = new EncryptedRTPSocket(null, port);
    >>>>> ctrlSock = new EncryptedRTPSocket(null, port
    + 1);
    >>>>> }
    >>>>> } catch (SocketException e) {
    >>>>> throw new IOException(e.getMessage());
    >>>>> }
    >>>>>
    >>>>> // Set the address and port
    >>>>> this.addr = addr; // this is _not_ the local address
    >>>>> this.port = port; // this is _not_ the local port #
    >>>>>
    >>>>> // Send out data to open the correct ports
    >>>>> dataSock.send(new DatagramPacket(new byte[100], 100,
    addr,
    >>>>> port));
    >>>>> ctrlSock.send(new DatagramPacket(new byte[100], 100,
    addr,
    >>>>> port + 1));
    >>>>> }
    >>>>>
    >>>>> This _always_ creates 2 new EncryptedRTPSocket (without
    encryption)
    >>>>> that in turn
    >>>>> open the data and control port on the local system (some comments
    >>>>> inserted by me).
    >>>>> The above example shows that the two .send(...) methods send the
    >>>>> data via
    >>>>> the port that was set via addTarget (addTarget defines a receiving
    >>>>> address and an
    >>>>> receiving port number of some system). In addition: sending
    >>>>> arbitrary data just
    >>>>> "to open a port" is not good practice - the receiver may not know
    >>>>> what to do with
    >>>>> it.
    >>>>>
    >>> <SNIP ---- SNAP>
    >>>
    >>>
    ---------------------------------------------------------------------
    >>> To unsubscribe, e-mail:
    dev-unsubscribe@sip-communicator.dev.java.net
    <mailto:dev-unsubscribe@sip-communicator.dev.java.net>
    >>> For additional commands, e-mail:
    dev-help@sip-communicator.dev.java.net
    <mailto:dev-help@sip-communicator.dev.java.net>
    >>>
    >>>
    >> ---------------------------------------------------------------------
    >> To unsubscribe, e-mail:
    dev-unsubscribe@sip-communicator.dev.java.net
    <mailto:dev-unsubscribe@sip-communicator.dev.java.net>
    >> For additional commands, e-mail:
    dev-help@sip-communicator.dev.java.net
    <mailto:dev-help@sip-communicator.dev.java.net>
    >>
    >>
    >
    >
    > ---------------------------------------------------------------------
    > To unsubscribe, e-mail:
    dev-unsubscribe@sip-communicator.dev.java.net
    <mailto:dev-unsubscribe@sip-communicator.dev.java.net>
    > For additional commands, e-mail:
    dev-help@sip-communicator.dev.java.net
    <mailto:dev-help@sip-communicator.dev.java.net>
    >
    >

    ---------------------------------------------------------------------
    To unsubscribe, e-mail:
    dev-unsubscribe@sip-communicator.dev.java.net
    <mailto:dev-unsubscribe@sip-communicator.dev.java.net>
    For additional commands, e-mail:
    dev-help@sip-communicator.dev.java.net
    <mailto:dev-help@sip-communicator.dev.java.net>

--
George Carlin - "Frisbeetarianism is the belief that when you die, your
soul goes up on the roof and gets stu...

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#8

Martin, Emil,

I'm just working on the problem. Analysing the code showed that
some classes/methods have to be modified. If all goes well I can
send a first path late afternoon today (Sunday 15th) to the list.

Regards,
Werner

PS: I'm also looking how to replace the Sun specific classes in FMJ,
for the JPEG codec classes in *.media.codec.video.jpeg.JPEGEncoder
I already found a solution (needs to be testet with a real media
file). Two others remain: a Base64 encoder/decoder - this is simple,
there are a lot of free base64 encoders around :slight_smile:
The last one is more comlicated: it's called JDK13Services. I didn't
found a good free replacement for it yet.

Replacing these classes would enable FMJ and in turn SC to use other
JRE/JDK implementations (openJDK, GNU Classpath, ...)

W.

Martin Harvan schrieb:

···

Hi Emil,
Yes I might take a look at it.. I am currently working on making the GSM
codec work, but that will not (hopefully) take much longer. After that I
will take a look at this issue.

On Sat, Jun 14, 2008 at 7:11 PM, Emil Ivov <emcho@sip-communicator.org> > wrote:

Hey folks,

Couldn't chime in on this one earlier (was a bit flooded lately). I just
wanted to mention that this is very important for us in SIP Communicator
and we heavily rely on such behaviour from JMF. In other words we expect
an RTPManager to use only one local socket (and hence port) for both
sending and receiving traffic associated with that manager.

We also currently rely on the fact that this would be the port indicated
in the SessionAddress that we pass to the manager in the initialize
method, as this way we can configure SC to use ports from specific range
which is important in case we want it to work behind a firewall that's
doing port forwarding for that range.

I was therefore thinking that in case Werner doesn't find the time to
come up with a patch, then Martin you might want to have a look at it
(provided this doesn't disrupt the GSoC schedule you have defined with
Ken of course). Ken, what do you think?

Cheers
Emil

Werner Dittmann ???:

yes, this tries to open a random port - however to send RTP data
FMJ shall use the same port as it uses to receive data (symmetrical
RTP) to avoid all sort problems with firewalls, media gateways (in
particualr Border Gateway Controllers) and some other "nasty" stuff :slight_smile:

I'll have a deeper look at this an propose a patch - this may take
some time, hopefully I can do it during the next weekend.

Regards,
Werner

Ken Larson schrieb:

my intention with that patch was to use the constructor to the socket
which does not specify the port, thereby opening a random (available)
port. It should no longer open the actual port specified on the local
system. Am I missing something?

Perhaps you could propose a patch to FMJ? That would be very helpful.

Ken

Werner Dittmann wrote:

Ken,

do you refer to the patch you sent to the mailing list yesterday?
If so then this patch does not solve the problem. It still opens
the ports that were set using "addTarget". The check isRTP() just

checks

if it is an even or odd portnumber (RTP data or control port according

to

rfc3550). As said the portnumber given to addTarget shall never be
opened on the local system. If you look at the usual use case in
SIP clients:

a SIP client determines which RTP ports (data/control) are available
at its system. The client opens these sockets for read/write and using
SIP/SDP it sends this information to the other client. This client in
turn determines which port numbers are available to it, opens these
sockets. Using addTarget() this second client adds the address and port
number to the RTP stack and can now send data to the other party. At
the same time it sends back its address/port information to the first
client. As said the port number received via SIP/SDP belongs to the
"remote" system and the "local" system shall not open it because it
may be used otherwise.

The current implementation uses the Encrypted sockets as underlying
socket framework. If FMJ is going to implement RTP encryption as

defined

in rfc3550 then this encrypted socket framework shall be adapted or
used in another way to fix the "open socket" problem.

I'll have a look into the multicast issue and give some feedback later.

Regards,
Werner

Ken Larson schrieb:

Does my patch solve the issue for you? Thanks, Ken.

Werner Dittmann wrote:

Maybe true - however IP based protocols may also be used on the same
system (locally) thus you may have applications on the same computer
that use RTP to communicate, also it's convenient for testing.

Even if it is an address of another system then the port number

belongs

to the other system, and not to the own system. Thus it is an error

to

open this port number on the local system because it may be
allocated to
yet another application.

With respect to JMF: the snippet below is a code snippet from a

working

JMF application. I have two RTP programs (clients) that communicate
using
RTP that work using JMF.

The different behavour is:

The first client opens port number 5002 to receive data from the
second client.
The second client opens port number 5004 to receive data from the
first client.

When I start the first client it opens port number 5002 _and_ port
number 5004,
thus the second client cannot open it's receiving port and fails

during

initialization.

The offending code is placed in RTPSessionMgr.addTarget(...) that
creates
a RTPSocketAdapter:

RTPSocketAdapter socket = new RTPSocketAdapter(
         localAddress.getDataAddress(),
         remoteAddress.getDataAddress(), remoteAddress.getDataPort(),
         remoteAddress.getTimeToLive());

This in turn uses the following constructor:

     /**
      * Creates a new RTPSocketAdaptor
      * @param laddr The local address to bind to
      * @param addr The address of the socket
      * @param port The port of the socket
      * @param ttl The ttl for sending data
      * @throws IOException I/O Exception
      */
     public RTPSocketAdapter(InetAddress laddr, InetAddress addr,
int port,
             int ttl)
             throws IOException {
         try {

             // If the address is multicast, create multicast
sockets and joing
             // groups etc
             if (addr.isMulticastAddress()) {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
                 //((MulticastSocket) dataSock).setInterface(laddr);
                 ((MulticastSocket) dataSock).joinGroup(addr);
                 ((MulticastSocket) dataSock).setTimeToLive(ttl);
                 ((MulticastSocket) dataSock).setLoopbackMode(false);
                 //((MulticastSocket) ctrlSock).setInterface(laddr);
                 ((MulticastSocket) ctrlSock).joinGroup(addr);
                 ((MulticastSocket) ctrlSock).setTimeToLive(ttl);
                 ((MulticastSocket) ctrlSock).setLoopbackMode(false);
             }

             // If the address is unicast, create unicast sockets
             else {
                 dataSock = new EncryptedRTPSocket(null, port);
                 ctrlSock = new EncryptedRTPSocket(null, port + 1);
             }
         } catch (SocketException e) {
             throw new IOException(e.getMessage());
         }

         // Set the address and port
         this.addr = addr; // this is _not_ the local address
         this.port = port; // this is _not_ the local port #

         // Send out data to open the correct ports
         dataSock.send(new DatagramPacket(new byte[100], 100, addr,
port));
         ctrlSock.send(new DatagramPacket(new byte[100], 100, addr,
port + 1));
     }

This _always_ creates 2 new EncryptedRTPSocket (without encryption)
that in turn
open the data and control port on the local system (some comments
inserted by me).
The above example shows that the two .send(...) methods send the
data via
the port that was set via addTarget (addTarget defines a receiving
address and an
receiving port number of some system). In addition: sending
arbitrary data just
"to open a port" is not good practice - the receiver may not know
what to do with
it.

<SNIP ---- SNAP>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail:

dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net