This document describes the extensions I've made to the DC protocol, to be
able to support extra functionality. Those are of course subject to change 
and discussion but I'll try to keep it as up to date as possible. Other 
clients are most welcome to follow this scheme and use the features 
presented here as they wish. The main scheme stems from a discussion 
sometime ago on the javadc-devel list on sourceforge...

Note; I assume familiarity with the dc protocol as used in neomodus dc 
1.00091...

The main idea behind the protocol is that when setting up the connection, 
each client tells the other one about all commands it understands, and 
after that, use those commands as pleased...to be able to do this we need 
to add a command to the protocol that tells the other client about the 
features it supports. We also need to make sure that only clients that
have a fair chance of understanding this command (to avoid unneccesary 
data being sent and to avoid confusing other clients). The scheme I've 
chosen is based on the $Lock information being sent upon setting up a 
connection, where a client that supports the extension command sends a 
special string in the lock, to let the other one know that it supports 
the extended commands. When having found such a client, it sends 
information about all features it supports before sending a correctly 
computed $Key.

On a side note; DC++ requires commands to come in a certain order to be 
able to efficiently use resources and will ignore any commands out of 
order (such as multiple $Send commands). This also improves the 
determinism of the protocol.


*** Client-Client communication ***

Feature: Supports

Purpose: To identify which features a certain client supports

Usage: "$Supports <feature1> <feature2> ... <featureN>|"
<featurename> = Case sensitive string describing the feature that a 
certain client supports. This should be the name of the command being 
sent, i e if a client supports a command "$GetBZListLen|", featurename 
should be GetBZListLen, unless of course, this is not a feature that 
requires sending extra data. Feature names may (obviously) not contain 
spaces. Empty $Supports should not be sent.

Should be sent: After receiving $Lock but before sending $Key

Notes: In the initial discussions, we thought about adding version 
information (something like "$Supports <name> <version>|"), but I've 
decided not to use this because 1) There could be problems with old 
versions, i e client x supports version 1.2, does that mean that it 
supports version 1.1 and 1.0 as well? 2) It's really easy to add a new 
version, i e "$Supports GetBZListLen GetBZListLen2|" to advertise an 
upgraded $GetBZListLen command.
This command should only be sent if the $Lock starts with the exact string 
EXTENDEDPROTOCOL", to avoid confusing clients that don't understand it
anyway. DC++ also uses the Pk part of the lock to identify exact client 
version, so a full $Lock string from a dc++ client is 
"$Lock EXTENDEDPROTOCOLxxxx Pk=DCPLUSPLUS0.164xxxx" where xxxx denotes 
some random data (not beginning with a number...=).

--------------------------------------------------------------------

Feature: BZList

Purpose: The file listing of a user is by default compressed with huffman 
encoding which is really inefficient. This feature adds the ability to get 
a file list compressed with bzip2 instead, which generally compresses 2-3 
times better (My 300kb list compressed to 210 kb with huffman and 82 kb 
with bzip2). This is a good thing because a) file lists can be transferred 
faster (specially on slower connections), b) bzip2 compression is very 
standard, c) It's a really easy feature to add (that's why I added it, to 
test this protocol extension scheme).

Usage: Normally, when getting a users file list, you use the command 
"$Get MyList.DcLst", where "MyList.DcList" is a unique filename that 
always denotes the users file listing. When a client supports BZList, it 
guarantees that the file "MyList.bz2" will always be available, and when 
decompressed, be exactly the same file as "MyList.DcLst".

Should be sent: Instead of "MyList.DcList" when getting a file list.

Note; libbzip2-1.0.2 (or a compatible library...) should be used for 
compression/decompression

--------------------------------------------------------------------

Feature: GetZBlock

Usage: Instead of $Get and $Send, use 
"$GetZBlock <start> <numbytes> <filename>|" where <start> is the 0-based
(yes, 0-based, not like get that's 1-based) starting index of the file 
used, <numbytes> is the number of bytes to send and <filename> obviously 
is the filename. The other client then responds 
"$Sending|<compressed data>", if the sending is ok or 
"$Failed <errordescription>|" if it isn't. If everything's ok, the data is 
sent until the whole uncompressed length has been sent. $Filelength or a 
similar command is never sent because it's not possible to know 
from the beginning how many bytes will be sent, instead, check how many 
decompressed bytes you've received and act accordingly...$Sending is 
needed to be able to distinguish the failure command from file data. Only 
one roundtrip is done for each block though, minimizing the need for 
maintaining states.

Compression: Compression is done using ZLib (v 1.1.4 in DC++ 0.21's case), 
using dynamic compression level. The compression level can of course be 
changed by the implementator to reduce CPU usage, or even just store 
compression in the case of non-compressible files, which then works as 
adler32 check of the transferred data.

--------------------------------------------------------------------

Feature: MiniSlots

Usage: This allows the other client to use a free slot for small files / 
file list. $Supports is needed because nmdc closes the file list browser
when the connection is broken, which it becomes when the client on the
other side tries to download its first file and fails because it has no
real slot (there were lots of nmdc users bitching about this...).

--------------------------------------------------------------------


*** Client-Hub communication ***

Feature: Supports

Usage: "$Supports <feature1> <feature2> ... <featureN>|"
This is mostly analogous to the client-client communcation part. The hub 
must send a $Lock that begins with "EXTENDEDPROTOCOL", which will prompt 
the client to answer with $Supports. Then, when a hub receives "$Supports" 
it _must_ answer with "$Supports" to tell the client about its features 
(which may differ from the ones the client supports). See client-client 
part for details. The hub must not send "EXTENDEDPROTOCOL" unless it 
supports at least one feature.

Should be sent: After $Lock, before $Key

--------------------------------------------------------------------

Feature: UserCommand

See dcplusplus.sf.net/wiki

--------------------------------------------------------------------

Feature: NoGetINFO

Usage: This indicates that hub doesn't need $GetINFO's to send out $MyINFO's
at connect. This is a sort of light-weight QuickList that's very easy to
implement and does half of QuickList's job.

--------------------------------------------------------------------

Feature: NoHello

Usage: This indicates that the client doesn't need neither $Hello nor $NickList
when connecting to a hub and receiving its users (i e $myinfo for each user is
enough). It still accepts $Hello though (to add bots to the user list),
and will still send getnicklist to indicate that it indeed is interested
in the user list. It still requires a $hello to be sent about itself during login!