MediaProxy throwing exceptions (when openfire is running on Windows)

I am trying to use the MediaProxy for passing UDP multimedia traffic between XMPP clients that I am writing a media extension to.

I have used the example on http://wiki.igniterealtime.org/display/WILDFIRE/Wildfire+Media+Proxy

to send and parse the needed relay setup stanza.

Unfortunately, when the server receives the first stanza from the XMPP client (asking to get a candidate) like;

<iq type=’‘get’’ id=’‘mediaRelayID’’ to=’'rtpbridge.xxx.com>

<rtpbridge xmlns=’‘http://www.jivesoftware.com/protocol/rtpbridge’’ sid=’‘somesessionName’’>

<candidate/>

</rtpbridge >

</iq>

The server replies with only portA attribute set to some port number while portB = 0 also it throws the following exception (reverse logged):

at java.lang.Thread.run(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)

at org.apache.mina.filter.executor.ExecutorFilter$ProcessEventsRunnable.run(Execut orFilter.java:326)

at org.apache.mina.filter.executor.ExecutorFilter.processEvent(ExecutorFilter.java :266)

at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceive d(AbstractIoFilterChain.java:800)

at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilt erChain.java:54)

at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(Ab stractIoFilterChain.java:362)

at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecF ilter.java:200)

at org.apache.mina.filter.codec.support.SimpleProtocolDecoderOutput.flush(SimplePr otocolDecoderOutput.java:62)

at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceive d(AbstractIoFilterChain.java:800)

at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilt erChain.java:54)

at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(Ab stractIoFilterChain.java:362)

at org.apache.mina.common.support.AbstractIoFilterChain$TailFilter.messageReceived (AbstractIoFilterChain.java:703)

at org.jivesoftware.openfire.nio.ConnectionHandler.messageReceived(ConnectionHandl er.java:132)

at org.jivesoftware.openfire.net.StanzaHandler.process(StanzaHandler.java:153)

at org.jivesoftware.openfire.net.StanzaHandler.process(StanzaHandler.java:254)

at org.jivesoftware.openfire.net.ClientStanzaHandler.processIQ(ClientStanzaHandler .java:79)

at org.jivesoftware.openfire.net.StanzaHandler.processIQ(StanzaHandler.java:289)

at org.jivesoftware.openfire.spi.PacketRouterImpl.route(PacketRouterImpl.java:67)

at org.jivesoftware.openfire.IQRouter.route(IQRouter.java:104)

at org.jivesoftware.openfire.IQRouter.handle(IQRouter.java:250)

at org.jivesoftware.openfire.mediaproxy.MediaProxyService.process(MediaProxyServic e.java:130)

at org.jivesoftware.openfire.mediaproxy.MediaProxyService.processIQ(MediaProxyServ ice.java:158)

at org.jivesoftware.openfire.mediaproxy.MediaProxy.addRelayAgent(MediaProxy.java:2 30)

at org.jivesoftware.openfire.mediaproxy.MediaProxy.addRelayAgent(MediaProxy.java:2 04)

at org.jivesoftware.openfire.mediaproxy.RelaySession.<init>(RelaySession.jav a:48)

at org.jivesoftware.openfire.mediaproxy.MediaProxySession.<init>(MediaProxyS ession.java:88)

at java.net.DatagramSocket.<init>(Unknown Source)

at java.net.DatagramSocket.<init>(Unknown Source)

at java.net.DatagramSocket.bind(Unknown Source)

at java.net.PlainDatagramSocketImpl.bind(Unknown Source)

at java.net.PlainDatagramSocketImpl.bind0(Native Method)

java.net.BindException: Cannot assign requested address: Cannot bind

]

2007.05.09 16:51:24 [org.jivesoftware.openfire.mediaproxy.MediaProxySession.<init>(MediaProxy Session.java:98)+++

I have looked at the code where it happens and it is unable to bind to a free port using DatagramSocket it was just few commands before binded too using ServerSocket.

Although the code is pure JAVA there is still a difference in the way sockets are behaving under Linux or Windows especially after socket is closing (TIME_WAIT etc). Yet, I did not see the socket being displayed with netstat.

Any idea? Can someone verify this is happening only on windows and not on Linux?

Thanks,

Arik.

Hello Arik,

You should try smackx-jingle.jar API to do this.

Use the following method of RTPBridge Class to get a candidate from the server.

public static RTPBridge getRTPBridge(XMPPConnection xmppConnection, String sessionID)

It’'s supposed to work on linux and windows.

Best Regards,

Thiago

Hi Thiago,

Sorry, but as far as I can see the XMPP request sent from my client to the server is the same as the one sent by calling getRTPBridge.

The problem is not on the client side (e.g. using smack or any other code) but rather on the server side

Could it be that the media proxy code missbehave on Windows? I know for sure there is a problem of reusing a socket that was recently closed (no matter if Java code or not), which is not an issue on Linux.

I also think it may have a another design bug there (see code snipt below) since after closing the socket in getFreePort the socket can be allocated to another process and hence cause the same exception as I have, although this is not my case since it seems like the bind fails. Why not create the socket once as DatagramSocket (inside getFreePort) and then pass it the caller? It will also save system resources and time (GC etc).


(MediaProxySession.java line 86)

this.localAddress = InetAddress.getByName(localAddress);

this.localPortA = getFreePort();

this.socketA = *new *DatagramSocket(localPortA, this.localAddress);

+this.socketAControl = *new *DatagramSocket(localPortA + 1, this.localAddress);+

this.localPortB = getFreePort();


and the code from GetFreePort() (MediaProxySession.java line 116):

ss = *new *ServerSocket(freePort);

freePort = ss.getLocalPort();

ss.close();

+ss = *new *ServerSocket(freePort + 1);+

controlPort = ss.getLocalPort();

ss.close();

+*if *(controlPort == (freePort + 1))+

  • *return *freePort;+

As far as I can see - the server is failing on the basic allocation of the MediaProxySession object.

Hope this helps to debug the issue.

Arik.

Hi Thiago

Ok, some update.

I debugged the server and found out that the problem lies in MediaProxySession.java

It seems that the server I am using is hosted behind a FW and a NAT and it cannot bind on its “external IP” as known outside the FW but only on the local IP which is not resolved (e.g. this.localAddress is something like myDomain.com which gets resolved to real IP address shared by many other machines and not the local LAN IP).

So I patched the server code as follows:

… MediaProxySession.java : line 88…

this.socketA = new DatagramSocket(localPortA); //, this.localAddress);

this.socketAControl = new DatagramSocket(localPortA + 1); //, this.localAddress);

this.localPortB = getFreePort();

this.socketB = new DatagramSocket(localPortB); //, this.localAddress);

this.socketBControl = new DatagramSocket(localPortB + 1); //, this.localAddress);

I suggest that this patch should also be inclueded in the upcoming server version unless there are other issues preventing it from getting in.

Thanks,

Arik.

This looks like it might also fix it…?

http://www.igniterealtime.org/issues/browse/JM-1052

But that’'s in 3.4.0 according to the tracker, not sure when that comes out.