Bug identified - No supported and enabled SASL Mechanism provided by server using BOSH connection

I was facing exactly issue mentioned in this Smack support forum. I had same behavior with BOSH client that after below code i get same error

connection.connect();
connection.login(username, password);

Now after deep study of code and debugging I identified root cause so posting in dev form. Though I found root cause I don’t know exact solution due to not fully aware of code and I hope dev team can fix it quickly.

Smack Version - 4.2.4
ejabberd version -18.04
OS - Windows 10

The scenario : issue comes when connect and login methods are called immediately one after other. Now in connect method, BoshClient is initialized and it starts new thread for RequestProcessor. Below is where RequestProcessor check for available SASL mechanism from server

"RequestProcessor[858232531]: Receive thread 0" #18 daemon prio=5 os_prio=0 tid=0x000000001bb09000 nid=0x37d8 at breakpoint[0x000000001d0be000]
   java.lang.Thread.State: RUNNABLE
	at org.jivesoftware.smack.util.PacketParserUtils.parseMechanisms(PacketParserUtils.java:704)
	at org.jivesoftware.smack.AbstractXMPPConnection.parseFeatures(AbstractXMPPConnection.java:1468)
	at org.jivesoftware.smack.bosh.XMPPBOSHConnection.access$1700(XMPPBOSHConnection.java:70)
	at org.jivesoftware.smack.bosh.XMPPBOSHConnection$BOSHPacketReader.responseReceived(XMPPBOSHConnection.java:523)
	at org.igniterealtime.jbosh.BOSHClient.fireResponseReceived(BOSHClient.java:1601)
	at org.igniterealtime.jbosh.BOSHClient.processExchange(BOSHClient.java:1136)
	at org.igniterealtime.jbosh.BOSHClient.processMessages(BOSHClient.java:990)
	at org.igniterealtime.jbosh.BOSHClient.access$300(BOSHClient.java:100)
	at org.igniterealtime.jbosh.BOSHClient$RequestProcessor.run(BOSHClient.java:1719)
	at java.lang.Thread.run(Thread.java:745)	

Once mechanism is parsed, it is available via SASLAuthentication.getServerMechanisms call during login which is happening in main thread

Thread [main] (Suspended (breakpoint at line 370 in SASLAuthentication))	
	owns: XMPPBOSHConnection  (id=52)	
	SASLAuthentication.getServerMechanisms() line: 370	
	SASLAuthentication.selectMechanism(EntityBareJid) line: 327	
	SASLAuthentication.authenticate(String, String, EntityBareJid, SSLSession) line: 192	
	XMPPBOSHConnection.loginInternal(String, String, Resourcepart) line: 222	
	XMPPBOSHConnection(AbstractXMPPConnection).login(CharSequence, String, Resourcepart) line: 491	
	XMPPBOSHConnection(AbstractXMPPConnection).login(CharSequence, String) line: 465	

Now what happens is, after SMPP server start, first time, the RequestProcessor thread goes through and made SASL mechanism available and login happens successfully. However after that second time, don’t understand why, but before RequestProcessor could parse mechanism reported by XMPP Server, login goes through. As mechanism is still not parsed, the login calls don’t get any SASL mechanism and it reports this error.
While debugging I saw that in after first login attempt to server, in next call RequestProcessor is always stuck waiting for response with below stacktrace and login continue advances further in main thread and finally giving this error.

"RequestProcessor[660895392]: Receive thread 1" #27 daemon prio=5 os_prio=0 tid=0x000000001ae36800 nid=0x2130 waiting on condition [0x000000001df3f000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x0000000081a168a0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at org.igniterealtime.jbosh.BOSHClient.nextExchange(BOSHClient.java:1023)
	at org.igniterealtime.jbosh.BOSHClient.processMessages(BOSHClient.java:965)
	at org.igniterealtime.jbosh.BOSHClient.access$300(BOSHClient.java:100)
	at org.igniterealtime.jbosh.BOSHClient$RequestProcessor.run(BOSHClient.java:1719)
	at java.lang.Thread.run(Thread.java:745)

To confirm this, in dobug mode, I just put break point at getServerMechanisms call in login flow and let RequestProcessor finish it work. In that case it always worked. So this is clearly multi threading issue. For now, I just applied workaround to get rid of issue by putting sleep before login call.

connection.connect();
Thread.sleep(5000);
connection.login(username, password);

I hope someone can fix this issue as early as possible in coming release. Application where there is natural delay between connect and login call may not have this issue.

Similar report at Getting Server did not report any SASL mechanisms sometimes

Smack’s BOSH code is old and not actively maintained. If you can’t fix it yourself (patches welcome) have a look at https://github.com/igniterealtime/Smack#professional-services