Mostly complete implementation of IRC v3 capability negotiation and SASL authentication.

This commit implements IRC v3 capability negotiation. A client
configuration option is provided to explicitly enable/disable IRC v3.
IRCv3 support will be enabled by default and may be enabled in specific
cases when IRC v3 support is explicitly not allowed. In case IRC v3
support is enabled, we will in all cases trigger capability negotiation,
though at this time, if we do not want to negotiate for SASL
authentication, there is no extension to negotiate for. In that case we
will issue CAP END to ensure that IRC server knows of our IRC v3
capabilities but do not engage in actual capability negotiation. If we
do not issue any command, there is a chance that an IRC server will
downgrade interoperation capabilities to the original RFC1459 feature
set.
maven
Danny van Heumen 11 years ago
parent c89234744b
commit 3a191411ce

@ -84,5 +84,6 @@
<classpathentry kind="lib" path="lib/installer-exclude/jcalendar-1.4.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/hsqldb.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/irc-api-1.0.jar" sourcepath="lib/installer-exclude/irc-api-1.0-sources.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/commons-codec-1.4.jar"/>
<classpathentry kind="output" path="classes"/>
</classpath>

@ -13,6 +13,16 @@
*/
public interface ClientConfig
{
/**
* Allow IRC version 3 capabilities.
*
* @return returns <tt>true</tt> if IRC version 3 capabilities are allowed,
* or <tt>false</tt> if we explicitly disallow anything related to
* IRCv3. (Disabling may regress the connection to "classic" IRC
* (RFC1459).)
*/
boolean isVersion3Allowed();
/**
* Enable contact presence periodic task for keeping track of contact
* presence (offline or online).

@ -19,6 +19,11 @@
public class ClientConfigImpl
implements ClientConfig
{
/**
* Allow IRC version 3 capabilities.
*/
private boolean version3Allowed = true;
/**
* Contact presence periodic task enable flag.
*/
@ -29,6 +34,27 @@ public class ClientConfigImpl
*/
private boolean channelPresenceTaskEnabled = true;
/**
* Get version 3 allowed flag.
*
* @return returns <tt>true</tt> if allowed, or <tt>false</tt> if not.
*/
@Override
public boolean isVersion3Allowed()
{
return this.version3Allowed;
}
/**
* Set version 3 allowed.
*
* @param allowed version 3 allowed
*/
public void setVersion3Allowed(final boolean allowed)
{
this.version3Allowed = allowed;
}
/**
* Get current value of contact presence enable flag.
*

@ -26,6 +26,9 @@
* TODO Query remote identity service for current identity-state such as:
* unknown, unauthenticated, authenticated.
*
* TODO Catch 900 (AUTHENTICATE LoggedIn) message and extract identity from
* there so that we do not have to do a separate WHOIS query.
*
* @author Danny van Heumen
*/
public class IdentityManager

@ -16,6 +16,7 @@
import com.ircclouds.irc.api.*;
import com.ircclouds.irc.api.domain.messages.*;
import com.ircclouds.irc.api.listeners.*;
import com.ircclouds.irc.api.negotiators.*;
import com.ircclouds.irc.api.state.*;
/**
@ -116,13 +117,17 @@ public class IrcConnection
* @param config client configuration
* @param irc the irc instance
* @param params connection parameters
* @param password the password for authentication
* @param connectionListener listener for callback upon connection
* interruption
* @param allowV3 Allow IRC version 3 capability negotiation. If not
* allowed, this may regress the IRC client to "classic" IRC
* (RFC1459)
* @throws Exception Throws IOException in case of connection problems.
*/
IrcConnection(final IrcStack.PersistentContext context,
final ClientConfig config, final IRCApi irc,
final IServerParameters params,
final IServerParameters params, final String password,
final IrcConnectionListener connectionListener)
throws Exception
{
@ -143,13 +148,25 @@ public class IrcConnection
this.irc = irc;
this.connectionListener = connectionListener;
// Prepare an IRC capability negotiator in case version 3 is allowed.
final CapabilityNegotiator negotiator;
if (config.isVersion3Allowed())
{
negotiator = determineNegotiator(params.getNickname(), password);
}
else
{
negotiator = null;
}
// Install a listener for everything that is not directly related to a
// specific chat room or operation.
this.irc.addListener(new ServerListener());
// Now actually connect to the IRC server.
this.connectionState =
connectSynchronized(this.context.provider, params, this.irc);
connectSynchronized(this.context.provider, params, password,
this.irc, negotiator);
// instantiate identity manager for the connection
this.identity =
@ -177,6 +194,35 @@ public class IrcConnection
new ServerChannelLister(this.irc, this.connectionState);
}
/**
* Determine which capability negotiator needed.
*
* Decide on which capability negotiator will be used in IRC server
* registration. The null negotiator is used to skip negotiation completely.
* This may regress the client connection to plain IRC (RFC1459) as defined
* in the specification
* (http://ircv3.atheme.org/specification/capability-negotiation-3.1).
*
* The NoopNegotiator should be used to do IRCv3 negotiation but not set up
* anything at that moment.
*
* @param user the user nick used for authentication
* @param password the authentication password
* @return returns capability negotiator
*/
private static CapabilityNegotiator determineNegotiator(final String user,
final String password)
{
if (password == null)
{
return new NoopNegotiator();
}
else
{
return new SaslNegotiator(user, password, null);
}
}
/**
* Perform synchronized connect operation.
*
@ -187,10 +233,15 @@ public class IrcConnection
*/
private static IIRCState connectSynchronized(
final ProtocolProviderServiceIrcImpl provider,
final IServerParameters params, final IRCApi irc) throws Exception
final IServerParameters params, final String password,
final IRCApi irc, final CapabilityNegotiator negotiator)
throws Exception
{
final Result<IIRCState, Exception> result =
new Result<IIRCState, Exception>();
// FIXME Decide between SASL authentication and normal 'PASS'-parameter
// authentication. You cannot do both as some services will respond with
// already-authenticated warning.
synchronized (result)
{
// start connecting to the specified server ...
@ -218,7 +269,7 @@ public void onFailure(final Exception e)
result.notifyAll();
}
}
});
}, negotiator);
provider.setCurrentRegistrationState(RegistrationState.REGISTERING,
RegistrationStateChangeEvent.REASON_USER_REQUEST);

@ -144,10 +144,11 @@ public void connect(final String host, final int port,
irc.addListener(new DebugListener());
}
// FIXME Add option to enable/disable IRCv3.
// Synchronized IRCApi instance passed on to the connection
// instance.
this.session.set(new IrcConnection(this.context, config, irc,
this.params, this));
this.params, password, this));
this.provider.setCurrentRegistrationState(
RegistrationState.REGISTERED,

@ -45,9 +45,10 @@ public SynchronizedIRCApi(final IRCApi irc)
@Override
public synchronized void connect(final IServerParameters aServerParameters,
final Callback<IIRCState> aCallback)
final Callback<IIRCState> aCallback,
final CapabilityNegotiator negotiator)
{
this.irc.connect(aServerParameters, aCallback);
this.irc.connect(aServerParameters, aCallback, negotiator);
}
@Override

@ -23,4 +23,7 @@ Import-Package: org.osgi.framework,
com.ircclouds.irc.api.domain.messages.interfaces,
com.ircclouds.irc.api.listeners,
com.ircclouds.irc.api.state,
org.apache.commons.lang3
com.ircclouds.irc.api.commands,
com.ircclouds.irc.api.negotiators,
org.apache.commons.lang3,
org.apache.commons.codec.binary

Loading…
Cancel
Save