Problem connecting to Wildfire through firewall

I have written an application that uses Smack to connect to a Wildfire server (version 3.0.1). When there are no firewalls involved, everything works fine. If I put the client machine behind a NAT firewall, it cannot connect to the Wildfire machine (which is not behind a firewall). From the client, I can ping the server and run the Wildfire web admin console, so outgoing connections are OK. Both machines are running WinXP and Java 1.6. When I run my client app, I get the following exceptions when it calls XMPPConnection.connect():

java.net.SocketException: Software caused connection abort: recv failed

at java.net.SocketInputStream.socketRead0(Native Method)

at java.net.SocketInputStream.read(Unknown Source)

at java.net.SocketInputStream.skip(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at org.jivesoftware.smack.XMPPConnection.proceedTLSReceived(XMPPConnection.java:11 87)

at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:343)

at org.jivesoftware.smack.PacketReader.access$000(PacketReader.java:45)

at org.jivesoftware.smack.PacketReader$1.run(PacketReader.java:77)

java.net.SocketException: Software caused connection abort: socket write error

at java.net.SocketOutputStream.socketWrite0(Native Method)

at java.net.SocketOutputStream.socketWrite(Unknown Source)

at java.net.SocketOutputStream.write(Unknown Source)

at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)

at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)

at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)

at sun.nio.cs.StreamEncoder.flush(Unknown Source)

at java.io.OutputStreamWriter.flush(Unknown Source)

at java.io.BufferedWriter.flush(Unknown Source)

at org.jivesoftware.smack.PacketWriter.writePackets(PacketWriter.java:275)

at org.jivesoftware.smack.PacketWriter.access$000(PacketWriter.java:39)

at org.jivesoftware.smack.PacketWriter$1.run(PacketWriter.java:91)

I tried running Spark 2.0.4 from the client machine to see if it could connect to the server, and it worked - I was able to log in as an existing user and send/receive chat messages to another client. However, when I tried to create a new user from Spark, it hung and the following exception showed up in error.log, which looks similar to the above errors:

java.net.SocketException: Socket closed

at java.net.SocketOutputStream.socketWrite(Unknown Source)

at java.net.SocketOutputStream.write(Unknown Source)

at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)

at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)

at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)

at sun.nio.cs.StreamEncoder.flush(Unknown Source)

at java.io.OutputStreamWriter.flush(Unknown Source)

at java.io.BufferedWriter.flush(Unknown Source)

at org.jivesoftware.smack.util.ObservableWriter.flush(ObservableWriter.java:48)

at org.jivesoftware.smack.PacketWriter.writePackets(PacketWriter.java:275)

at org.jivesoftware.smack.PacketWriter.access$000(PacketWriter.java:39)

at org.jivesoftware.smack.PacketWriter$1.run(PacketWriter.java:91)

javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

at com.sun.net.ssl.internal.ssl.InputRecord.handleUnknownRecord(Unknown Source)

at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at org.jivesoftware.smack.XMPPConnection.proceedTLSReceived(XMPPConnection.java:11 87)

at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:343)

at org.jivesoftware.smack.PacketReader.access$000(PacketReader.java:45)

at org.jivesoftware.smack.PacketReader$1.run(PacketReader.java:77)

Exception in thread “Thread-2” java.lang.NullPointerException

at org.jivesoftware.AccountCreationWizard$3.construct(AccountCreationWizard.java:1 87)

at org.jivesoftware.spark.util.SwingWorker$2.run(SwingWorker.java:132)

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

Does anyone know what could be causing this?

Message was edited by: svattom

I think I have solved my problem, but I don’'t understand why the solution works. I wrote a small test application to demonstrate the problem, and as I was step-debugging it, it worked OK a few times. I noticed that if I waited long enough between calling XMPPConnection.connect and XMPPConnection.login, it would work. So I tried setting the Smack packet reply timeout to 10 seconds (default is 5 seconds) by calling SmackConfiguration.setPacketReplyTimeout(10000), and this solved the problem.

I dug around a little more, and I found that in the Spark source code, the default timeout is 10 seconds (quite a coincidence) , and this is set just before logging in. This explains the results of my Spark tests above - logging in as an existing user works, but creating a new account fails because it is still using the default timeout of 5 seconds. This raises a few questions:

  1. Why does 10 seconds work but 5 seconds fails?

  2. Why is 5 seconds the default when 10 seconds is known to work better?

  3. What does the firewall have to do with any of this?

Anyway, since it is working for me now, I will mark the question as answered. Also, here is the code for my test app and some sample output for firewalled and non-firewalled tests.

import org.jivesoftware.smack.Chat;

import org.jivesoftware.smack.SmackConfiguration;

import org.jivesoftware.smack.XMPPConnection;

public class TestXMPP

{

private static long time;

public static void main(String[] args) throws Exception

{

if (args.length = 5)

{

int timeout = Integer.parseInt(args[4]);

System.out.println(“Setting packet reply timeout to " + timeout + " ms”);

SmackConfiguration.setPacketReplyTimeout(timeout);

}

System.out.println(“Connecting”);

conn.connect();

logTime();

System.out.println("Logging in as " + userName);

conn.login(userName, password);

logTime();

System.out.println("Creating chat to " + otherUser);

Chat chat = conn.createChat(otherUser);

logTime();

System.out.println(“Sending message”);

chat.sendMessage(“TestXMPP”);

logTime();

System.out.println(“Disconnecting”);

conn.disconnect();

logTime();

System.out.println(“DONE”);

}

private static void logTime()

{

long diff = System.currentTimeMillis() - time;

System.out.println(" Done (" + diff + " ms)");

time = System.currentTimeMillis();

}

}

Non-firewalled output:

Creating XMPPConnection to hostname

Done (266 ms)

Setting packet reply timeout to 10000 ms

Connecting

Done (500 ms)

Logging in as x

Done (93 ms)

Creating chat to y@hostname

Done (16 ms)

Sending message

Done (0 ms)

Disconnecting

Done (2000 ms)

DONE

Firewalled output:

Creating XMPPConnection to hostname

Done (15234 ms)

Setting packet reply timeout to 10000 ms

Connecting

Done (20688 ms)

Logging in as x

Done (125 ms)

Creating chat to y@hostname

Done (0 ms)

Sending message

Done (0 ms)

Disconnecting

Done (172 ms)

DONE