- Contents
- Format
- Propagation
- Connection setup
- Modes
- Required core commands
- Optional core commands
- Extension commands
JELP
The Juno Extensible Linking Protocol (JELP) is the preferred server linking protocol for juno-to-juno links.
As of writing, the only implementation known to exist is that of juno itself, but future applications may choose to implement JELP for better compatibility with juno.
This document is to be used as reference when implementing IRC servers and pseudoservers.
- Format
- Propagation
- Connection setup
- Modes
- Required core commands
- Optional core commands
- Extension commands
Format
The protocol resembles RFC1459 in that
each message represents a command with an optional source, target, and
additional parameters. The source is prefixed by a colon (:
), as is the final
parameter if it includes whitespace.
Most messages resemble the following:
:<source> <command> [<parameters> ...]
However, a few do not require a source:
<command> [<parameters> ...]
Some also include message tags.
Line delimiters
A single message occurs per line. Empty lines are silently discarded.
The traditional line ending \r\n
(CRLF) is replaced simply by \n
(LF);
however for easier adoption in legacy software, \r
MUST be ignored if present.
The traditional line length limit of 512 bytes does not apply, nor do any limitations on the number of parameters per message. For this reason it is especially important that only trusted servers are linked. However, servers MAY choose to terminate an uplink if the receive queue exceeds a certain size.
Entity identifiers
The protocol is further distinguished from RFC1459 by its use of user and server identifiers as the source and target of commands in place of nicknames, user masks, and server names. This idea is borrowed from other server linking protocols such as TS6; it aims to diminish the effects of name collisions.
-
SID - A server identifier. This is numerical (consisting of digits 0-9).
-
UID - A user identifier. This consists of ASCII letters (a-z, A-Z), prefixed by the numerical SID to which the user belongs. It is case-sensitive.
User and server identifiers in JELP are of arbitrary length but limited to 16 bytes. Servers SHOULD NOT use the prefix on UIDs to determine which server a user belongs to. Servers MAY reuse UIDs that are no longer active should the 16 byte limit be exhausted.
Message tags
Some messages have named parameters called tags. They occur at the start of the message, before the source and command. The format is as follows:
@<name>=<value>[;<name2>=<value2> ...] :<source> <command> [<parameters> ...]
This is particularly useful for messages with optional parameters (as it reduces overall message size when they are not present). More often, however, it is used to introduce new fields without breaking compatibility with existing implementations.
This idea is borrowed from an extension of the IRC client protocol, IRCv3.2 message-tags. The JELP implementation of message tags is compatible with that specification in all respects, except that the IRCv3 limitation of 512 bytes does not apply.
Propagation
-
server mask - command is propagated based on a server mask parameter. The command is sent to all servers with names matching the given mask (for example
*
,*.example.com
,irc.example.com
). Those servers do not have to be directly connected. -
broadcast - command is sent to all servers.
-
one-to-one - command is only sent to the target or the server the target is on.
-
conditional - propagation is dependent on command interpretation and is described in the text. It may also be used to describe another propagation type where the command may or may not be propagated based on its interpretation.
-
none - command is never sent to another server if it is received.
Connection setup
-
Server negotiation - The initiator sends the
SERVER
command. The receiver verifies the server name, SID, TS, peer address, and versions. If unacceptable, the connection is dropped before password negotiation; otherwise, the receiver replies with its ownSERVER
command. -
Password negotiation - If the incoming
SERVER
passes verification, the initiator sendsPASS
. The receiver verifies the password, dropping the connection if invalid. If the password is correct, the receiver replies with its ownPASS
command, followed byREADY
. -
Initiator burst - Upon receiving
READY
, the initiator sends its burst, delimited byBURST
andENDBURST
. -
Receiver burst - Upon receiving
ENDBURST
, the receiver replies with its own burst.ENDBURST
andREADY
should be handled the same way: in either case, the server sends its burst if it has not already.
Burst
A server burst consists of the following:
-
Initiate the burst with
BURST
- Send out this server's mode mappings
- Introduce descendant servers
- Introduce users
-
Burst channels
-
SJOIN
- bursts modes, membership -
TOPICBURST
- bursts topic -
MLOCK
- bursts mode lock
-
-
Extensions
-
Any extension burst commands occur here, such as
BAN
-
Any extension burst commands occur here, such as
-
Terminate the burst with
ENDBURST
Modes
JELP does not have predefined mode letters. Before any mode strings are sent
out, servers MUST send the AUM
and ACM
commands to map mode
letters and types to their names. Servers SHOULD track the mode mappings of all
other servers on the network, even for unrecognized mode names.
Throughout this documentation, commands involving mode strings will mention a perspective, which refers to the server whose mode letter mappings should be used in the parsing of the mode string. If the perspective is a user, it refers to the server to which the user is connected.
Below are the lists of mode names, their types, and their usual associated letters. Servers MAY implement any or all of them, but they MUST quietly ignore any unrecognized incoming modes.
Required core commands
These commands MUST be implemented by servers. Failure to do so will result in network discontinuity.
ACM
Maps channel mode letters and types to mode names.
Propagation: broadcast
:<SID> ACM <name>:<letter>:<type> [<more modes> ...]
- SID - server these mode mappings belong to
- name - mode name
- letter - mode letter
-
type - mode type, which describes how to allocate parameters in a mode string. one of
-
0
- normal mode, no parameter -
1
- mode with parameter always -
2
- mode with parameter only when setting -
3
- banlike list mode -
4
- status mode -
5
- channel key (special case)
-
AUM
Maps user mode letters to mode names.
Propagation: broadcast
:<SID> AUM <name>:<letter> [<more modes> ...]
- SID - server these mode mappings belong to
- name - mode name
- letter - mode letter
AWAY
Marks a user as away.
Propagation: broadcast
:<UID> AWAY [:<reason>]
- UID - user to mark as away
- reason - optional, reason for being away. if omitted, the user is returning from away state
BURST
Sent to indicate the start of a burst.
This is used for the initial burst as well as the bursts of other descendant servers introduced later.
The corresponding ENDBURST
terminates the burst.
Propagation: broadcast
:<SID> BURST <TS>
- SID - server bursting
- TS - current UNIX TS
CMODE
Channel mode change.
Propagation: conditional broadcast
:<source> CMODE <channel> <TS> <perspective> <modes> [<parameters> ...]
- source - user or server committing the mode change
- channel - channel to change modes on
- TS - channel TS
- perspective - mode perspective server
- modes - mode changes. each mode parameter is a separate parameter of the command
If <TS>
is newer than the internal channel TS, drop the message and do not
propagate it.
Otherwise, accept and propagate the incoming modes.
ENDBURST
Sent to indicate the end of a burst.
Propagation: broadcast
:<SID> ENDBURST <TS>
- SID - server whose burst has ended
- TS - current UNIX TS
Upon receiving, the server should send its own burst if it has not already.
JOIN
Channel join. Used when a user joins an existing channel with no status modes.
Propagation: broadcast
:<UID> JOIN <channel> <TS>
- UID - user joining the channel
- channel - channel being joined
- TS - channel TS
If <channel>
does not exist, create it. This should not happen though.
If <TS>
is older than the internal channel TS, reset all channel modes and
invitations.
Regardless of <TS>
, add the user to the channel and propagate the JOIN
with
the CURRENT channel TS.
See also SJOIN
.
KICK
Propagates a channel kick. Removes a user from a channel.
Propagation: broadcast
:<source> KICK <channel> <target UID> :<reason>
- source - user or server committing the kick
- channel - channel to remove the target user from
- target UID - user to remove
- reason - kick comment
KILL
Temporarily removes a user from the network.
Propagation: broadcast
:<source> KILL <target UID> :<reason>
- source - user or server committing the kill
- target UID - user to remove
- reason - kill comment, visible as part of the user quit message
KILL is not acknowledged (it is NOT followed by QUIT), and for that reason, it cannot be rejected. Pseudoservers whose clients cannot be killed may internally disregard the KILL message but, in that case, must immediately reintroduce the user to uplinks.
NICK
Propagates a nick change.
Propagation: broadcast
:<UID> NICK <nick> <nick TS>
- UID - user changing nicks
- nick - new nick
- nick TS - new nick TS
NOTICE
To the extent that concerns JELP, equivalent to PRIVMSG
in all
ways other than the command name.
Propagation: conditional
NUM
Sends a numeric reply to a remote user.
Propagation: one-to-one
:<SID> NUM <UID> <num> :<message>
- SID - source server
- UID - target user (determines propagation)
- num - numeric, a three-digit sequence
- message - numeric message
If <num>
starts with 0
, rewrite the first digit as 1
. This is because the
numerics in the 0XX
range are permitted only from the server the user is
connected to.
Note that <message>
may actually contain several numeric parameters combined
into a single string. It may also contain a sentinel (in addition to the usual
one which prefixes it) at the start or later in the message. For this reason,
<message>
should not be prefixed with a sentinel when forwarding it to the
target user.
OPER
Propagates oper privileges.
The setting of the ircop
user mode (+o) is used to indicate that a user has
opered-up; this command may be used to modify their permissions list.
Propagation: broadcast
:<UID> OPER [-]<flag> [<flag> ...]
- UID - user whose privileges are to be changed
-
flag - any number of oper flags may be added or removed in a single message, each as a separate parameter. those being removed are prefixed by
-
; those being added have no prefix
PART
Propagates a channel part.
Propagation: broadcast
:<UID> PART <channel> :<reason>
- UID - user to be removed
- channel - channel to remove the user from
PARTALL
Used when a user leaves all channels.
This is initiated on the client protocol with the JOIN 0
command.
Propagation: broadcast
:<UID> PARTALL
- UID - user to be removed from all channels
PASS
During registration, sends the connection password.
Propagation: none
PASS <password>
- password - connection password in plain text
See connection setup.
PING
Verifies uplink reachability.
Propagation: none
PING <message>
-
message - some data which will also be present in the corresponding
PONG
PONG
Reply for PING
.
Propagation: none
:<SID> PONG <message>
- SID - server replying to the PING
-
message - data which was specified in the corresponding
PING
PRIVMSG
Sends a message.
Propagation: conditional
:<source> PRIVMSG <target> :<message>
- source - user or server sending the message
- target - message target, see below
- message - message text
<target>
can be any of the following:
-
a user
- Propagation: one-to-one
-
a channel
- Propagation: all servers with non-deaf users on the channel
-
@
followed by a status mode letter and a channel name, to message all users on the channel with that status or higher- Propagation: all servers with -D users of appropriate status
-
Example:
@o#channel
- all users on #channel with+o
or higher
-
=
followed by a channel name, to send to channel ops only, for op moderation- Propagation: all servers with -D channel ops
-
a
[email protected]
message, to send to users on a specific server. the exact meaning of the part before the@
is not prescribed, except that "opers" allows IRC operators to send to all IRC operators on the server in an unspecified format. this can also be used for more secure communications to external services -
a message to all users on server names matching a mask (
$$
followed by mask)- Propagation: broadcast
- Only allowed to IRC operators
-
a message to all users with hostnames matching a mask (
$#
followed by mask)- Unimplemented
- Propagation: broadcast
- Only allowed to IRC operators
QUIT
Propagates a user or server quit.
Propagation: broadcast
Form 1
:<UID> QUIT :<reason>
- UID - user quitting
- reason - quit comment
Form 2
[@from=] :<SID> QUIT :<reason>
- from - optional, user that initiated the SQUIT
- SID - server quitting
- reason - quit comment
READY
Sent to indicate that the initiator should send its burst.
Propagation: none
READY
See connection setup.
SAVE
Used to resolve nick collisions without casualty.
Propagation: broadcast
:<SID> SAVE <UID> <nick TS>
- SID - server saving the user
- UID - user to be saved
- nick TS - user's nick TS, as known by the saving server
If the user target already has their UID as their nick or <nick TS>
does not
match the internal nick TS, drop the message and do not propagate.
Otherwise, change the user's nickname to their UID, set their nick TS to 100, and propagate the message.
SERVER
During registration, introduces the server.
Propagation: none
SERVER <SID> <name> <proto version> <version> <TS> :<description>
- SID - server ID
- name - server name
- proto version - JELP protocol version (checked for compatibility)
- version - IRCd or package version (not checked)
- TS - current UNIX TS
-
description - server description to show in
LINKS
,MAP
, etc. This MUST be the last parameter, regardless of any additional parameters which may be added in between the<TS>
and<description>
at a later date. If the description starts with the sequence(H)
(including the trailing space), the server should be marked as hidden
See connection setup.
SID
Introduces a server.
Propagation: broadcast
:<source SID> SID <SID> <name> <proto version> <version> <TS> :<description>
- source SID - parent server
- SID - server ID
- name - server name
- proto version - JELP protocol version (checked for compatibility)
- version - IRCd or package version (not checked)
- TS - current UNIX TS
-
description - server description to show in
LINKS
,MAP
, etc. This MUST be the last parameter, regardless of any additional parameters which may be added in between the<TS>
and<description>
at a later date. If the description starts with the sequence(H)
(including the trailing space), the server should be marked as hidden
SJOIN
Bursts a channel.
This command MUST be used for channel creation and during burst. It MAY be used for existing channels as a means to grant status modes upon join.
Propagation: broadcast
:<SID> SJOIN <channel> <TS> <modes> [<parameters> ...] :<user list>
- SID - server bursting the channel
- channel - channel being burst or created
- TS - channel TS
-
modes - all channel modes besides statuses. each mode parameter is a separate parameter of the
SJOIN
command. if no modes are set, a single+
must be present -
user list - membership and status modes. this will always be the last parameter, regardless of any mode parameters before it. the format is a space-separated of
UID!modes
, wheremodes
are the status modes that the user has in the channel. if a user has no modes, the!
may be omitted
If the channel does not exist, create it.
Otherwise:
If <TS>
is older than the internal channel TS, clear all modes and invites,
accept new modes and statuses, and forward as-is.
If <TS>
is equal to the current internal channel TS, accept new modes and
statuses and forward as-is.
If <TS>
is newer than the current internal channel TS, disregard modes and
statuses and forward the message without them.
In any case, add the listed users to the channel.
TOPIC
Propagates a channel topic change.
Propagation: broadcast
:<source> TOPIC <channel> <TS> <topic TS> :<topic text>
- source - user or server setting the topic
- channel - channel whose topic is being changed
- TS - channel TS
- topic TS - new topic TS
- topic text - new topic text
Regardless of <TS>
, set the topic and propagate it with the CURRENT channel
TS.
TOPICBURST
Bursts a channel topic.
Propagation: broadcast
:<SID> TOPICBURST <channel> <TS> <set by> <topic TS> :<topic text>
- SID - server bursting the topic
- channel - channel whose topic is being burst
- TS - channel TS
- set by - server name or user mask that set the topic
- topic TS - new topic TS
- topic text - new topic text
Accept the topic and propagate if any of the following are true:
- the channel currently has no topic
-
<TS>
is older than the internal channel TS -
<TS>
is equal to the internal channel TS and<topic TS>
is newer than the internal topic TS
Otherwise, drop the message and do not propagate.
UID
Introduces a user.
Propagation: broadcast
:<SID> UID <UID> <nick TS> <modes> <nick> <ident> <host> <cloak> <ip> :<realname>
- SID - server to which the user belongs
- UID - UID
- nick TS - nick TS
-
modes - user modes in the perspective of
<SID>
(no parameters) or a single+
if no modes are set - nick - nick
- ident - ident/username
- host - real canonical host
- cloak - visible host
-
ip - IP address. must be prefixed with
0
if starts with:
- realname - real name
UMODE
Propagates a user mode change.
Propagation: broadcast
:<UID> UMODE <modes>
- UID - user whose modes are to be changed
-
modes - modes in the perspective of
<UID>
(no parameters)
USERINFO
Propagates the changing of one or more user fields.
Propagation: broadcast
[@nick=][;nick_time=][;real_host=][;host=][;ident=][;account=] :<UID> USERINFO
- nick - optional, new nick
-
nick time - optional, new nick time. MUST be present if
<nick>
is present - real_host - optional, new real canonical host
- host - optional, new visible canonical host
- ident - optional, new ident/username
-
account - optional, new account name or
*
for logout - UID - user whose fields should be changed
Optional core commands
These commands SHOULD be implemented by servers when applicable, but failure to do so will not substantially affect network continuity.
ADMIN
Remote ADMIN
request.
Propagation: one-to-one
:<UID> ADMIN <server>
- UID - user making the request
-
server - server name or
$
-prefixed SID (determines propagation)
CONNECT
Remote CONNECT
.
Propagation: one-to-one
:<source> CONNECT <mask> <server>
- source - user or server initiating the CONNECT
- mask - parameter for CONNECT command. this may be an absolute server name or a mask matching zero or more servers
-
server - server name or
$
-prefixed SID (determines propagation)
FJOIN
Forces a user to join a channel.
Propagation: one-to-one
:<SID> FJOIN <UID> <channel> [<TS>]
- SID - server committing the force join
- UID - user to force to join (determines propagation)
- channel - channel to force the user to join
- TS - optional, channel TS
If <TS>
is provided, the channel must exist, and the internal channel TS
must match the provided one. If this is not the case, drop the message. The
server must handle the request as though it were a normal JOIN message from the
client, taking bans and other restrictions into account.
If <TS>
is omitted, the join should be forced regardless of whether the
channel is preexisting or has restrictions to prevent the user from joining.
In either case, if the join was successful, the server must acknowledge the
join with either SJOIN
(if the channel was just created) or
JOIN
(otherwise).
FLOGIN
Forces a user to login to an account.
Used by external services.
Propagation: broadcast
:<SID> FLOGIN <UID> <account>
- SID - server forcing the login
- UID - user to force to login
- account - name of the account
Unlike other force commands, FLOGIN
cannot fail and therefore does not need to
be acknowledged.
FNICK
Forces a nick change.
Propagation: one-to-one
:<SID> FNICK <UID> <new nick> <new nick TS> <old nick TS>
- SID - server forcing the nick change
- UID - user whose nick should be changed (determines propagation)
- new nick - new nick
- new nick TS - new nick TS
- old nick TS - old nick TS
If <old nick TS>
is not equal to the internal nick TS, drop the message.
Otherwise, if the new nick is already in use by an unregistered connection, cancel registration and drop that connection.
If the new nick is already in use by a user, kill the user.
Update the nick and nick TS and acknowledge the change by broadcasting a
NICK
message to all servers including the one which issued FNICK
.
FOPER
Forces an oper privilege change.
Propagation: one-to-one
:<SID> FOPER <UID> [-]<flag> [<flag> ...]
- SID - server forcing the privilege change
- UID - user whose privileges will be changed (determines propagation)
-
flag - any number of oper flags may be added or removed in a single message, each as a separate parameter. those being removed are prefixed by
-
; those being added have
Update the flags and acknowledge the change by broadcasting an
OPER
message to all servers including the one which issued FOPER
.
FPART
Forces a user to part a channel.
Propagation: one-to-one
:<SID> FPART <UID> <channel> <TS> [:<reason>]
- SID - server forcing the user to part
- UID - user to force to part (determines propagation)
- TS - channel TS
- reason - optional, part reason
Commit the mode change and acknowledge it by broadcasting a
PART
message to all servers including the one which issued FPART
.
FUMODE
Forces a user mode change.
Propagation: one-to-one
:<SID> FUMODE <UID> <modes>
- SID - server forcing the mode change
- UID - user whose modes should be changed (determines propagation)
-
modes - modes in the perspective of
<UID>
(no parameters)
Remove the user from the channel and acknowledge the change by broadcasting a
UMODE
message to all servers including the one which issued
FUMODE
.
FUSERINFO
Forces the changing of one or more user fields.
Propagation: one-to-one
See USERINFO
for fields.
The receiver may accept or reject any of the changes. Acknowledge those which
were accepted with a USERINFO
message broadcast to all servers
including the one which issued FUSERINFO
.
INFO
Remote INFO
request.
Propagation: one-to-one
@for= :<UID> INFO
- for - server target (determines propagation)
- UID - user committing the request
INVITE
Invites a remove user to a channel.
Propagation: one-to-one
:<UID> INVITE <target UID> <channel>
- UID - user offering the invitation
- target UID - user to be invited (determines propagation)
- channel - channel to which the user should be invited
<channel>
does not necessarily have to exist, but servers MAY silently discard
invitations to nonexistent channels to prevent spam.
KNOCK
Propagates a channel knock.
Propagation: broadcast
:<UID> KNOCK <channel>
- UID - user knocking
- channel - channel to knock on
LINKS
Remote LINKS
request.
Propagation: one-to-one
@for= :<UID> LINKS
- for - server target (determines propagation)
- UID - user committing the request
LOGIN
Propagates a user account login.
Propagation: broadcast
:<UID> LOGIN <account info>
- UID - user to login
- account info - comma-separated account info. the format is unspecified except that the first field is always the account name
Currently, <account info>
is only the account name. In previous built-in
account mechanisms, other data was also sent. For compatibility in case a future
account mechanism makes use of other fields, the account name should be
extracted as the sequence terminated by either ,
or the end of the string.
LUSERS
Remote LUSERS
request.
Propagation: one-to-one
@for= :<UID> LUSERS
- for - server target (determines propagation)
- UID - user committing the request
MLOCK
Sets a channel mode lock.
:<source> MLOCK <channel> <TS> <modes> [<parameters> ...]
- source - user or server committing the mode lock
- channel - channel to lock the modes on
- TS - channel TS
-
modes - optional, modes to lock. each mode parameter is a separate parameter of the command. for status modes, the parameter should be the mask which is locked. for all other modes with parameters, the parameter value does not matter but must be present.
*
is used as a filler
If <TS>
is newer than the internal channel TS, drop the message and do not
propagate it.
Otherwise, if <modes>
is omitted, unset the current mode lock and propagate
the message with the current channel TS.
Otherwise, set the mode lock locally and propagate the message with the current channel TS and the mode string exactly as it was received.
MOTD
Remote MOTD
request.
Propagation: one-to-one
:<UID> MOTD <server>
- UID - user committing the request
-
server - server name or
$
-prefixed SID (determines propagation)
REHASH
Remote REHASH
.
Propagation: server mask
:<UID> REHASH <mask>
- UID - user committing the request
- mask - server mask target. all matching servers will respond (determines propagation)
SNOTICE
Propagates a server notice to remote opers.
Propagation: broadcast
[@from_user=] :<SID> SNOTICE <flag> :<message>
- from_user - optional, user whose action resulted in this notice
- SID - server producing the notice
- flag - server notice flag
- message - notice text
TIME
Remote TIME
request.
Propagation: one-to-one
:<UID> TIME <server>
- UID - user committing the request
-
server - server name or
$
-prefixed SID (determines propagation)
USERS
Remote USERS
request.
Propagation: one-to-one
@for= :<UID> USERS
- for - server target (determines propagation)
- UID - user committing the request
VERSION
Remote VERSION
request.
Propagation: one-to-one
:<UID> VERSION <server>
- UID - user committing the request
-
server - server name or
$
-prefixed SID (determines propagation)
WHOIS
Remote WHOIS
query.
Propagation: one-to-one
@for= :<UID> WHOIS <target UID>
- for - server target (determines propagation)
- UID - user committing the request
- target UID - user whose information is being requested
Extension commands
These commands MAY be implemented by servers but are not required. They are not part of the core JELP protocol implementation. If any unknown command is received, servers MAY choose to produce a warning but SHOULD NOT terminate the uplink.
BAN
During burst, lists all known global ban identifiers and the times at which they were last modified.
Propagation: none
BANIDK
In response to BAN
during burst, requests information for a ban the
receiving server is not familiar with.
Propagation: none
BANINFO
Propagates a global ban.
Used upon adding a new ban and during burst in response to BANIDK
.
Propagation: broadcast
MODEREP
MODEREQ
Used for MODESYNC.
SASLDATA
SASLDONE
SASLHOST
SASLMECHS
SASLSET
SASLSTART
Used for SASL authentication.