Login hangs

Hello,

I am trying to connect my Spark client through a proxy server using last Smack 3.1.0 library. The proxy I use is an Http proxy and when I supply the correct proxy settings I log successfully through it.

Some times, like when I introduce as protocol “SOCKS” (a wrong one), login panel hang ups in instruction “connection.connect()” (connection is a Xmppconnection). I have put a timer in order to exit this code and then change proxy settings to right ones.

My problem is that when I change the protocol to “HTTP” and try to connect with the correct settings after the timer, the applications hangs again. If I close the application and try again, it works.

I have examined the open connections in my computer before exiting and I can see two established TCP connections to my proxy server (every attemp, SOCKS and HTTP has opened one). This connections only shut down when I completely close muy application.

How can I completely close this connection before every attemp without exiting as this seems to be the problem? After my timer completes, the variable xmppconnection has not connected, so I can not close it to try again, but the proxy server’s tcp connection keeps established.

Any idea?

Sorry, I should have attached my code:

        boolean hasErrors = false;
        String errorMessage = null;

// Handle specifyed Workgroup
String serverName = getServerName();

if (!hasErrors) {
localPref = SettingsManager.getLocalPreferences();
if (localPref.isDebuggerEnabled()) {
XMPPConnection.DEBUG_ENABLED = true;
}

SmackConfiguration.setPacketReplyTimeout(localPref.getTimeOut() * 1000);

// Get connection
try {
int port = localPref.getXmppPort();

int checkForPort = serverName.indexOf(":");
if (checkForPort != -1) {
String portString = serverName.substring(checkForPort + 1);
if (ModelUtil.hasLength(portString)) {
// Set new port.
port = Integer.valueOf(portString);
}
}

boolean useSSL = localPref.isSSL();
boolean hostPortConfigured = localPref.isHostAndPortConfigured();

ConnectionConfiguration config;

if (useSSL) {
if (!hostPortConfigured) {
config = new ConnectionConfiguration(serverName, 5223);
config.setSocketFactory(new DummySSLSocketFactory());
}
else {
config = new ConnectionConfiguration(localPref.getXmppHost(), port, serverName);
config.setSocketFactory(new DummySSLSocketFactory());
}
}
else {
if (!hostPortConfigured) {
config = new ConnectionConfiguration(serverName);
}
else {
config = new ConnectionConfiguration(localPref.getXmppHost(), port, serverName);
}
}

                //--------------------------------smack 3.1.0: proxy-----------------------------------------//
                if (localPref.isProxyEnabled())
                {
                 if (getProxyInfo() == null)
                  return false;
                 //Obtenemos el puerto al que conectarnos cuando usemos proxy.
                 int portWhenProxy = 443;
                 System.out.println("LOGIN >> Proxy Enabled: " + "[XmppPortWhenProxyEnabled = " + portWhenProxy + "]");
                 System.out.println("LOGIN >> Setting PROXY CONFIG");
                 System.out.println("LOGIN >>   [Host     = " + localPref.getHost() + "]");
                 System.out.println("LOGIN >>   [Port     = " + localPref.getPort() + "]");
                 System.out.println("LOGIN >>   [Username = " + localPref.getProxyUsername() + "]");
                 System.out.println("LOGIN >>   [Protocol = " + localPref.getProtocol() + "]");
                 System.out.println("LOGIN >> Setting PROXY CONFIG END");
                 if (useSSL) {
                     if (!hostPortConfigured) {
                      config = new ConnectionConfiguration(serverName, portWhenProxy, getProxyInfo());
                     }
                     else {
                      config = new ConnectionConfiguration(localPref.getXmppHost(), portWhenProxy, serverName, getProxyInfo());
                     }
                     config.setSocketFactory(new DummySSLSocketFactory());
                    }
                    else {
                     if (!hostPortConfigured) {
                      config = new ConnectionConfiguration(serverName, portWhenProxy, getProxyInfo());
                     }
                     else {
                      config = new ConnectionConfiguration(localPref.getXmppHost(), portWhenProxy, serverName, getProxyInfo());
                     }
                    }
                }
                //----------------------------------------------------------------------------- --------------//

                // smack 3.1.0: muy importante añadir esta línea para mantener equivalencia con pila anterior
                // a la hora de logarse y recibir el roster. Ya que:
                // "connection.login(getUsername(), getPassword(), resource, false)"  equivale a
                // "config.setSendPresence(false)" + "connection.login(getUsername(), getPassword(), resource)"
                config.setSendPresence(false);
                //

               
               
                if (localPref.isPKIEnabled()) {
                    SASLAuthentication.supportSASLMechanism("EXTERNAL");
                    config.setKeystoreType(localPref.getPKIStore());
                    if(localPref.getPKIStore().equals("PKCS11")) {
                        config.setPKCS11Library(localPref.getPKCS11Library());
                    }
                    else if(localPref.getPKIStore().equals("JKS")) {
                        config.setKeystoreType("JKS");
                        config.setKeystorePath(localPref.getJKSPath());

}
else if(localPref.getPKIStore().equals(“X509”)) {
//do something
}
else if(localPref.getPKIStore().equals(“Apple”)) {
config.setKeystoreType(“Apple”);
}
}

if (config != null) {
config.setReconnectionAllowed(true);
boolean compressionEnabled = localPref.isCompressionEnabled();
config.setCompressionEnabled(compressionEnabled);

                    connection = new XMPPConnection(config,this);
                    if(ModelUtil.hasLength(localPref.getTrustStorePath())) {
                        config.setTruststorePath(localPref.getTrustStorePath());
                        config.setTruststorePassword(localPref.getTrustStorePassword());
                    }
                }

//new method
final ConnectionConfiguration conf = config;
final SwingWorker ConThread;
final SwingWorker WaitThread;
WaitThread = new SwingWorker() {
public Object construct() {
try {
int sec = 30;
Thread.sleep( sec * 1000 );
} catch (InterruptedException e) {
//e.printStackTrace();
return null;
}
return true;
}
};
ConThread = new SwingWorker() {
public Object construct() {
try {
System.out.println(“LOGIN >> Connecting to… [Host=”+conf.getHost()+"] [ServiceName="+conf.getServiceName()+"] [Port="+conf.getPort()+"]");
connection.connect();
System.out.println(“LOGIN >> …successfully connected to. [Host=”+connection.getHost()+"] [ServiceName="+connection.getServiceName()+"] [Port="+connection.getPort()+"] [ConnectionID="+connection.getConnectionID()+"]");

                   String resource = localPref.getResource();
                   if (!ModelUtil.hasLength(resource))
                       resource = "spark";

System.out.println(“LOGIN >> Logging in… [serverName=”+getServerName()+"] [username="+getUsername()+"] [password="+getPassword()+"] [resource="+resource+"]");
// smack 3.1.0
//connection.login(getUsername(), getPassword(), resource, false);
connection.login(getUsername(), getPassword(), resource);
//
System.out.println(“LOGIN >> …successfully logged in. [serverLogicName=”+connection.getServiceName()+"] [jid="+connection.getUser()+"]");

                   sessionManager.setServerAddress(connection.getServiceName());
                   sessionManager.initializeSession(connection, getUsername(), getPassword());
                   sessionManager.setJID(connection.getUser());
                   WaitThread.interrupt();
    return true;
   } catch (XMPPException e) {
    //e.printStackTrace();
    WaitThread.interrupt();
    return e;
   }
           }
          
          };
          WaitThread.start();
          ConThread.start();
          if (WaitThread.get()!=null) //waitthread ended OK-->timeout expired
          {
           ConThread.interrupt();
           System.out.println("LOGIN >> Login TIMEOUT expired");
           throw new XMPPException(new XMPPError(XMPPError.Condition.remote_server_error));
          }
          else //waitthread ended NO OK-->conthread ended before
          {
           if (ConThread.get() instanceof XMPPException)
           {//conthread ended NO OK --> throw its object
            XMPPException e = (XMPPException)ConThread.get();
            System.out.println("LOGIN >> THROW XMPPException: [XMPPerror="+e.getXMPPError()+"] [msg="+e.getMessage()+"] [localizedMsg="+e.getLocalizedMessage()+"]");
            //Utility.traceStackTrace();
            throw e;
           }
           //conthread ended OK --> continue
          }
          System.out.println("LOGIN >> Login SUCCEED");
          //
            }
            catch (Exception xee) {
                if (!loginDialog.isVisible()) {
                    loginDialog.setVisible(true);
                }
                if (xee instanceof XMPPException) {
                    XMPPException xe = (XMPPException)xee;
                    final XMPPError error = xe.getXMPPError();
                    int errorCode = 0;
                    if (error != null) {
                        errorCode = error.getCode();
                    }
                    if (errorCode == 401) {
                        errorMessage = Res.getString("message.invalid.username.password");
                    }
                    else if (errorCode == 502 || errorCode == 504) {
                        errorMessage = Res.getString("message.server.unavailable");
                    }
                    else if (errorCode == 409) {
                        errorMessage = Res.getString("label.conflict.error");
                    }
                    else {
                        errorMessage = Res.getString("message.unrecoverable.error");
                    }
                }
                else {
                    errorMessage = SparkRes.getString(SparkRes.UNRECOVERABLE_ERROR);
                }

// Log Error
Log.warning(“Exception in Login:”, xee);
hasErrors = true;

                System.out.println("LOGIN >> ...login failed [errormessage="+errorMessage+"] [errorNativeMessage="+xee.getMessage()+"]");
            }
        }
        if (hasErrors) {
        
         //smack 3.1.0
         if ( (connection!=null)&&(connection.isConnected()) )
         {
          connection.disconnect();
         }
           
            progressBar.setVisible(false);
            //progressBar.setIndeterminate(false);
           
            // Show error dialog
            if (loginDialog.isVisible()) {
                if (!localPref.isSSOEnabled()) {
                    JOptionPane.showMessageDialog(loginDialog, errorMessage, Res.getString("title.login.error"),
                            JOptionPane.ERROR_MESSAGE);
                }
                else {
                    JOptionPane.showMessageDialog(loginDialog, "Unabled to connect using Single Sign-On. Please check your principal and server settings.", Res.getString("title.login.error"),
                            JOptionPane.ERROR_MESSAGE);
                    //useSSO(false);
                    //localPref.setSSOEnabled(false);
                }
            }
            setEnabled(true);
            return false;
        }

// Since the connection and workgroup are valid. Add a ConnectionListener
connection.addConnectionListener(SparkManager.getSessionManager());

// Persist information
localPref.setUsername(getUsername());

// Check to see if the password should be saved.
if (savePasswordBox.isSelected()) {
String encodedPassword;
try {
encodedPassword = Encryptor.encrypt(getPassword());
localPref.setPassword(encodedPassword);
}
catch (Exception e) {
Log.error(“Error encrypting password.”, e);
}
}
else {
localPref.setPassword("");
}

localPref.setSavePassword(savePasswordBox.isSelected());
localPref.setAutoLogin(autoLoginBox.isSelected());

if (localPref.isSSOEnabled()) {
localPref.setAutoLogin(true);
}

localPref.setServer(serverField.getText());

        SettingsManager.saveSettings();

return !hasErrors;
}

private boolean login() {
final SessionManager sessionManager = SparkManager.getSessionManager();

I realized that when you change yout type of proxy server (SOCKS or HTTP), the system properties related with proxy configuration were not correctly updated.

I have solved this, and now, I am able to log with a HTTP server after trying with a wrong SOCKS server (without closing Spark application).

Anyway, the connection to the server in the first wrong attempt isn’t still closed. Any idea to close permanently this connection from my code?

Thanks in advance.