Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IRCv3 3.1 base extensions + away-notify #27

merged 36 commits into from Jun 9, 2015


Copy link

This is an implementation of IRCv3 with capability negotiation support + base extensions + away-notify.
(Please note that this PR also contains the error handling changes previously proposed. Let me know if you want to take another approach to this, I can probably split it up, but for now I decided to leave this in.)

irc-api is modified to allow for providing capability negotiators and there are a number of negotiators implemented by default.

  • NoopNegotiator if you just want to signal to the IRC server your understanding of IRCv3 but do not want to negotiate capabilities,
  • SaslNegotiator if you only want to add SASL negotiation to your IRC connection,
    SaslCapability is also available in case you need more capabilities than just SASL authentication.
  • CompositeNegotiator if you want to negotiate for an arbitrary number of capabilities.

The CompositeNegotiator may be provided with a list of capabilities, which will all be negotiated, and a host interface to which will be called back with the negotiation result.

This implementation assumes that the client application is the primary user of IRCv3's features and therefore irc-api does not do the actual negotiation. This way you can add capabilities to negotiate for even if irc-api does not support these. If these capabilities extend existing IRC commands, you may need to add support to irc-api, however for any new commands and features, you can just handle those in the client application itself. (In a previous commit, an UnknownMessage message type was added, so you are able to handle messages not known by irc-api.)

Additionally, irc-api is modified to handle multiple prefixes in NAMES / WHO messages. Therefore, if 'multi-prefix' extension is enabled, irc-api will be able to make use of the extra information. Most notably, by providing all relevant IRC user modes, instead of just the one that was communicated.

Lastly, an AwayMessage type is created and handling of these messages is provided. If 'away-notify' is negotiated and supported by IRC server, then enabling this, will allow irc-api to transparently handle Away-messages and notify listeners via the onAwayMessage event. For irc-api there is nothing to do apart from routing the message to listeners via the correct event.

With this PR, there is support for IRCv3 3.1 base extensions + away-notify at the very least. Other extensions may work out-of-the-box as most of them need to be handled by the client application anyway, but the lower bound is IRCv3 3.1 so far.

Let me know what you think. Any feedback is welcome.

SocketException exceptions are fatal for communication, so we dispatch
an error to inform listeners that an error has occurred.
A basic implementation of CAP (capability) negotiation. This
implementation adds a mechanism for providing an "external" negotiator.
The negotiator will be called before registering with the IRC server in
order to query the desired CAP init command.

Then, if a negotiator is provided, it will be registered as a general
message handler, such that it can keep track of messages that are
communicated. As irc-api itself does not support CAP messages, it is
expected that the CapabilityNegotiator instance will then take over and
handle CAP negotiations. Once CAP END is sent, normal registration
procedure will take over and the server will send msg 001 and continue
with normal registration procedure.
… of the states.

A simplistic implementation that tries to keep strict states by
implementing each state in its own subclass and throwing
IllegalStateExceptions for all operations that are not allowed in the
current state.

Improvements are pending that make the state machine in itself more
intelligent such that the logic is in the state itself. This will make
error handling easier as knowledge of the current state is available.
States now communicate themselves. Not sure how to handle fail()
messages: do nothing, abort, retry with preconstructed prepare message,
...? Plus some other outstanding TODOs/FIXMEs.
While looking into other authentication mechanisms for IRC sasl extension,
there appear to be a number of other options available. These mechanisms
provide additional security in some kind or another. But there's still
some discussion going on about what is most reliable, so for now I'll
leave some notes only.
… capabilities.

An initial implementation of a composite negotiator that can do the
negotiation for a list of basic capabilities. Basic capabilities are
capabilities which can only be turned on or off and do not require
additional conversation with the IRC server itself.

The implementation supports acked capabilities and will automatically
send the client ACK in case this is required by the IRC server.
Lots of changes:
* Support for capability conversations.
* New SimpleCapability for simple binary (enable/disable) capabilities.
* New SASL capability for use in CompositeNegotiator with other
* Migrated SASL state machine to separate class SaslStateMachine.
* Simplified SASL state machine: dropped intermediate state that really
belonged to the CAP negotiation not SASL negotiation.
* Introduced Relay type for limited access to IRC server for
* Fixed bug where requestedCapabilities would use wrong collection for
deriving requestable capabilities.
…edback of connection failure in case of connection cut off during IRC registration process.
As a Java hint described, we can make use of a EnumMap here. This map
is optimized for enums and will allocate and operate more efficiently.
IRCv3 3.1 defines the capability away-notify. This capability provides a
switch to enable away notifications for all channel members that you
share a channel with.

irc-api is modified to be able to handle this message in its message
handling infrastructure. A new event 'onUserAway' is defined for
handling away notifications.
1. Clean up a number of FIXMEs.
2. Fine tuning of SASL capability for various server responses. Be more
specific in waiting for server message after fail() call and stop
3. End capability negotiation if ServerNumericMessage 001 is
encountered. (And log encounter.)
4. Make better use of logging API to prevent unnecessary string concat.
5. Created RawMessageUtils for some basic utility methods on raw IRC
6. Now mutates this.requested in CompositeNegotiator in order to detect
whether all requested capabilities have been acknowledged. Until this
list is empty, assume that server will send additional messages
containing the remaining this.requested capabilities.
7. Added warning in case CAP REQ message is too large. Multiple request
are not supported yet, but at least it does not go unnoticed.
8. Removed use case of "lost" capability, instead assume that another
CAP ACK messages is coming which contains this capability.
9. Added TODO for special exception that would signal aborting IRC
registration process. This can be used (among others) by SASL capability
to signal aborting in case of failed SASL authentication and
authentication is a prerequisite for IRC connection.

The previous method for encoding to base64 would automatically include
newlines for readability. Now using the byte[] variant which only does
"raw" encoding.
1. SaslContext is more strict: does not allow fail() abort() before
init() is called.
2. Moved information on SASL authentication choices to SaslContext
class, as it is more appropriate there.
3. Modified behaviour in SaslNegotiator in some error handling cases.
4. Added more tests.
Restored the original connect(...) method to not break backwards
compatibility. Also added a significant amount of documentation to refer
to the various negotiators that can be used upon connecting and
explained the semantics of a null negotiator.
cobratbq added a commit to jitsi/libsrc that referenced this pull request May 30, 2015
This modified code is based on commit
81e24e4e063eb02ae1247a681bb7c41b44cd4e5b of (new home for irc-api after
announced shutdown of

A pull request for integration of the modifications into irc-api master
branch is created: migzai/irc-api#27
migzai added a commit that referenced this pull request Jun 9, 2015
IRCv3 3.1 base extensions + away-notify
@migzai migzai merged commit 5245946 into migzai:master Jun 9, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

Successfully merging this pull request may close these issues.

None yet

2 participants