News |
Latest network news: Opertest policy update and DarkFire now on a T1 Connection!.
|
|
|
CTCP and DCC Information
===========================================
A description of the CTCP and DCC protocols
===========================================
This document will briefly describe the Direct Client-to-Client
protocol (DCC) and the Client-To-Client Procotol (CTCP).
The description of CTCP is divided in two sections, a basic
and one of a more technical nature.
The DCC Protocol
================
This protocol was first designed to be used with the IRC client
IrcII. However, it has been "adopted" by many other clients,
and today almost every IRC client supports DCC.
What is DCC ?
-------------
DCC enables users to exchange information without being bound
by some IRC server limitations.
DCC uses direct TCP connections between the clients taking part
to carry data. There is no flood control, so packets can be sent
at full speed, and there is no dependance on server links (or load
imposed on them). In addition, since only the initial handshake
for DCC conections is passed through the IRC network, it is
impossible for Operators to monitor DCC sessions in any way.
The initial DCC negotiation
---------------------------
When a client (the initiator) wishes to establish a DCC session
with another user, the initiating client will open a passive
(listening) TCP socket bound to INADDR_ANY, port 0.
Then, the client will send its details to the target client,
using the CTCP command DCC. The command will be:
DCC type argument address port
where
type = the connection type
argument = the connection type dependant argument
address = the host address of the initiator as an interger.
port = the port or the socket on which the initiator expects
to receive the connection.
The most common DCC connection types are:
Type Purpose Argument
CHAT To carry a secure conversation The string "chat"
SEND To send a file to the receipient The filename
--
Initiator:
DCC command issued.
Create a socket, bind it to INADDR_ANY, port 0, and make it passive.
Send the recipient a DCC request via CTCP supplying the address
and port of the socket. (This is ideally taken from the address of
the local side of the socket which is connected to a side of the
socket which is connected to a server. This is presumably the
interface on the host which is closest to the rest of the net,
and results in one less routing hop in the case of gateway nodes).
Continue normally until a connection is received.
On a connection:
Accept the connection.
Close the original passive socket.
Conduct transaction on the new socket.
Acceptor:
CTCP DCC request received.
Record information on the DCC request and notify the user.
At this point, the USER should be able to abort (close) the request,
or accept it. The request should be accepted with a command specifying
the sender, type, and argument, or a subset of these where no ambiguity
exists.
If accepted, create a TCP socket. Connect the new socket to the address
and port supplied. Conduct the transaction over the socket.
Type specific details
---------------------
CHAT:
Data sent across a CHAT connection should be sent line-by-line without
any prefixes or commands. A CHAT connection ends when one party issues
the DCC CLOSE command to their clients, which causes the socket to be
closed and the information on the connection to be discarded.
FILE:
Data is sent in packets, rather than dumped in a stream manner. This
allows the DCC SEND connection to survive where an FTP connection
might fail. The size of the packets is up to the client, and may be
set by the user. Smaller packets result in a higher probability of
survival over bad links. The recipient should acknowledge each
packet by transmitting the total number of bytes received as an
unsigned, 4 byte integer in network byte order. The sender should
not continue to transmit until the recipient has acknowledged all
data already transmitted. Additionally, the sender should not close
the connection until the last byte has been acknowledged by the recipient.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The Client-To-Client Protocol
=============================
The Client-To-Client Protocol is sent and interpreted by the IRC client.
Therefore, CTCP does not have anything to do with the IRC server,
although CTCP messages do "travel through IRC". Servers treats CTCPs
just like any other PRIVMSG or NOTICE.
In CTCP, there are two forms of communication: COMMAND and REPLY.
Commands will be sent like a PRIVMSG's while replies will be sent
like NOTICE's.
A basic explanation
-------------------
This section will give a basic idea of what happens when you send and
receives CTCP's.
COMMANDS are send as follows:
PRIVMSG :\001 \001
\001 is the delimiter character:
X-DELIM ::= '\001'
See the advanced CTCP section for more info on this.
And REPLIES in this format:
NOTICE :\001 \001
The most common commands are:
CLIENTINFO, ACTION, DCC, ERRMSG, FACE, FINGER, PING, SOUND,
SOURCE, TIME, USERINFO, VERSION, and XDCC.
Briefly, this is what each command does:
CLIENTINFO -- Display valid CTCP commands for that client.
ACTION -- when you type /me does this, it is actually sent
as a CTCP message. However, unlike other CTCP commands, it
does not require a REPLY, and none should be given.
DCC -- DCC is established by CTCP, however it is not
conducted over CTCP. See the section on DCC for more
information on this protocol.
ERRMSG -- Reply to unknown CTCP command.
FACE -- Pictographic 32x32 pixel representation of user
(Macintosh clients only)
FINGER -- Shows idletime of client, usually with an e-mail
address and message.
PING -- Used to measure lag, or the time it takes for
information to travel between servers.
SOUND -- Causes the client(s) that receive it to play a
sound file.
SOURCE -- A URL where the client/script can be obtained.
TIME -- Local time of recipient.
USERINFO -- Shows a "witty" saying set by user.
VERSION -- Replies with IRC client version.
Example:
I want to ping #darkfire:
PRIVMSG #darkfire :\001PING 966780265\001
All users on #darkfire will receive this. They could see this:
:Gizmo!dsrna@aus.silkets.dk PRIVMSG #darkfire :\001PING 966780265\001
And they would all reply with:
NOTICE Gizmo :\001PING 966780265\001
Which will be seen as:
:Skinner!sjm076@ppp-per-217.ca.com.au NOTICE Gizmo :\001PING 966780265\001
Gizmo's client would then interpret this as being a reply to a PING and
process it accordingly, in this case, taking the timestamp (966780265)
and subtracting it from the current timestamp.
Advanced CTCP
-------------
Although the section above explain how CTCP's are sent through the IRC
server, there are more to it, which will be explained here.
Characters between client and server are 8-bit bytes (also known as octets)
and can have numeric values from octal 0 up to 0377 inclusive (0 up to 255
decimal). Some characters are special.
CHARS ::= '\000' .. '\377'
NUL ::= '\000'
NL ::= '\n'
CR ::= '\r'
A line sent to a server, or received from a server (here called
"low-level messages") consist or zero or more octets (except NUL, NL or CR)
with either a NL or CR appended.
Low-level quoting:
As messages to and from servers can't contain NUL, NL and CR, but it still
might be desirable to send ANY character (in so called "middle level
messages") between clients, those three characters have to be quoted.
Therefore a quote character is needed. Of course, the quote character
itself has to be quoted too.
M-QUOTE ::= '\020'
(Ie a CNTRL/P).
When sending a middle-level message, if finding a character being one
of NUL, NL, CR or M-QUOTE, that character is replaced by a two-character
sequence according to the following table.
NUL --> M-QUOTE '0' NL --> M-QUOTE 'n' CR --> M-QUOTE 'r'
M-QUOTE --> M-QUOTE M-QUOTE
When receiving a low-level message and seeing a M-QUOTE, look at the next
character, and replace those two according to the following table to get
the corresponding middle-level message.
M-QUOTE '0' --> NUL M-QUOTE 'n' --> NL M-QUOTE 'r' --> CR
M-QUOTE M-QUOTE --> M-QUOTE
If the character following M-QUOTE isn't any of the listed characters,
that is an error, so drop the M-QUOTE character from the message,
optionally warning the user about it. Ie, a string 'x' M-QUOTE 'y' 'z'
from a server dequotes into 'x 'y' 'z'.
Before low-level quoting, a message to the server (and in the opposite
direction, after low-level dequoting, a message from the server) looks
like
M-LINE ::= CHARS*
Tagged data
-----------
To send both extended data and query/reply pairs between clients, an
extended data format is needed. The extended data are sent in the text
part of a middle-level message (and after low-level quoting of course
also in the text part of the low-level message).
To send extended data inside the text, we need some way to delimit it.
This is done by starting and ending extended data with a delimiter
character.
X-DELIM ::= '\001'
As both the starting and ending delimiter looks the same, every second
X-DELIM is called the odd, and every second the even delimiter. The
first one in a message is odd.
When having being quoted (and conversely, before having been dequoted)
any number of characters of any kind except X-DELIM can be used in the
extended data, i.e., inside the X-DELIM pair.
X-CHR ::= '\000' | '\002' .. '\377'
An extended message is either empty (i.e., nothing between the odd and
even delimiter), has one or more non-space characters (i.e., any
character but '\040') or has one or more non-space characters followed
by a space followed by zero or more characters.
X-N-AS ::= '\000' | '\002' .. '\037' | '\041' .. '\377' SPC ::= '\040'
X-MSG ::= | X-N-AS+ | X-N-AS+ SPC X-CHR*
The first characters up until the first SPC (or if no SPC, all of the
X-MSG) is called the tag of the extended message. The tag is used to
know what kind of extended data is used.
The tag can be any string of characters, and if they happen to be
letters, they are case-sensitive, so upper- and lowercase matters.
Extended data is only valid in PRIVMSG and NOTICE commands. If the
extended data is a reply to a query, it is sent in a NOTICE, or
else it is sent in a PRIVMSG. Both PRIVMSG and NOTICE to a user
and to a channel may contain extended data.
The text part of a PRIVMSG or NOTICE might contain zero or more
extended messages, intermixed with zero or more chunks of non-
extended data.
CTCP level quoting
------------------
In order to be able to send the delimiter X-DELIM inside an extended
data message, it has to be quoted. This introduces another quote
character (which should differ from the low-level quote character so
it won't have to be quoted yet again).
X-QUOTE ::= '\134'
(i.e., a backslash).
When quoting on the CTCP level, only actual CTCP messages (ie
extended data, queries, replies) are quoted. This enables users to
actually send X-QUOTE characters at will. The following translations
should be used:
X-DELIM --> X-QUOTE 'a' X-QUOTE --> X-QUOTE X-QUOTE
When dequoting on the CTCP level, only CTCP messages are dequoted,
whereby the following table is used:
X-QUOTE 'a' --> X-DELIM X-QUOTE X-QUOTE --> X-QUOTE
If a X-QUOTE is seen with another the character following it than the
ones above, that constitutes an error, and the X-QUOTE character
should be dropped. For example, the CTCP-quoted string 'x' X-QUOTE
'y' 'z' becomes after dequoting the three character string 'x' 'y' 'z'.
If a X-DELIM is found outside a CTCP message, the message will contain
the X-DELIM. (This should only happen with the last X-DELIM when there
are an odd number of X-DELIM's in a middle-level message.
Quoting examples
----------------
If the user actor wants to query the USERINFO of user victim, and is in
the middle of a conversation, the client may decide to tack on USERINFO
request on a normal text message. Then the client wants to send the
textmessage "Say hi to Ron\n\t/actor" and the CTCP request "USERINFO"
to victim.
PRIVMSG victim :Say hi to Ron\n\t/actor
plus
USERINFO
which after CTCP quoting become
PRIVMSG victim :Say hi to Ron\n\t/actor
plus
USERINFO
which gets merged into
PRIVMSG victim :Say hi to Ron\n\t/actor\001USERINFO\001
and after low-level quoting
PRIVMSG victim :Say hi to Ron\020n\t/actor\001USERINFO\001
and sent off to the server.
On victim's side, the message
:actor PRIVMSG victim :Say hi to Ron\020n\t/actor\001USERINFO\001
arrives. This gets low-level dequoted into
:actor PRIVMSG victim :Say hi to Ron\n\t/actor\001USERINFO\001
and thereafter split up into
:actor PRIVMSG victim :Say hi to Ron\n\t/actor
plus
USERINFO
After CTCP dequoting both, the message
:actor PRiVMSG victim :Say hi to Ron\n\t/actor
gets displayed, while the CTCP command
USERINFO
gets replied to. The reply might be
USERINFO :CS student\n\001test\001
which gets CTCP quoted into
USERINFO :CS student\n\\atest\\a
and sent in a NOTICE as it is a reply:
NOTICE actor :\001USERINFO :CS student\n\\atest\\a\001
and low-level quoted into
NOTICE actor :\001USERINFO :CS student\020n\\atest\\a\001
after which is it sent to victim's server.
When arriving on actor's side, the message
:victim NOTICE actor :\001USERINFO :CS student\020n\\atest\\a\001
gets low-level dequoted into
:victim NOTICE actor :\001USERINFO :CS student\n\\atest\\a\001
At this point, all CTCP replies get extracted, giving 1 CTCP reply and no
normal NOTICE
USERINFO :CS student\n\\atest\\a
The remaining reply gets CTCP dequoted into
USERINFO :CS student\n\001test\001
and presumably displayed to user actor.
--- End of document.
Written for the DarkFire IRC network 1999
by S. Nielsen aka (Gizmo@darkfire.net)
|
|
|