Edit by Mutor

Introduction

I have compiled this protocol documentation from various sources in hopes of creating a complete Direct Connect protocol reference.

The following users have contributed to this file.

Sid, aDe, Sedulus, David Marwood, Suxxx, Stefan Gorling, Sphinx & HaArD

The Direct Connect network is composed of Hubs, Clients, and the HubListServer. Hubs listen on TCP port 411 and allow many clients to connect and exchange commands such as searches and chat messages. Essentially, hubs are a naming service and communication facilitator for clients. Clients store files and respond to searches against those files. The HubListServer acts as a naming service for all the hubs. All hubs register with the HubListServer and clients discover hubs by asking the HubListServer. Clients are run by users, each of whom has a nick (aka username).

The TCP data is a series of commands, each in the form of,

The | indicates the end of a command and is not followed by a newline.

Certain users are designated as Ops by the hub and are able to issue certain commands not available to other users.

Table Of Contents

Introduction -- Introduction

Client2Client_Handshake -- Client to Client HandShake Client2Server_Login -- Client to Server Login Server2RegServer_HubRegistration -- Server to Hub Registration Server Communication
Command_Types_(client_to_client) -- Command Types (client to client)
Command_Types_(client_to_server) -- Command Types (client to server) Command_Types_(server_to_server) -- Command Types (server to server)
Command_Types_(experimental) -- Command Types (experimental)
Appendix_A -- Converting a Lock into a Key
Appendix_B -- Creating a Lock

<Introduction / Contents>

Client to Client HandShake

$MyNick

The listen User sends his Name when a user connecting.

The $Lock is sent immediately after the $MyNick command within the same packet.

Immediately following the $MyNick + $Lock packet the connecting user sends their $MyNick + $Lock in the same fashion as above.

$Direction

The $Direction command is a part of the response packet to the $Lock + $MyNick packet.

After the $Direction command we must send the $Key command (still with in the $Direction packet) in response to the other clients lock.

The users are now connected.

$Send

The $Send command informs the uploading client, that the download will start.

Direct Connect sends upload data in chunks of 40906 bytes. After every 40906 bytes is recived the downloading client must send the $Send again.


Download Example:

	Client <-> Client Communication in DC. 11-05-2002. By aDe 
	---------------------------------------------------------- 

	ACTIVE FILE DOWNLOAD 
	---------------------- 
	D = downloader 
	U = uploader 
	H = hub 

	D>H: $ConnectToMe <U's username> <D's IP and port>|
	H>U: $ConnectToMe <U's username> <D's IP and port>|
	U>D: Connection
	U>D: $MyNick <U's nick>|$Lock <new lock with pk>|
	D>U: $MyNick <D's nick>|$Lock <new lock with pk>|$Direction Upload <anumber>|$Key <key for U's lock>|
	U>D: $Direction Download <anumber>|$Key <key for D's lock>|
	D>U: $Get <filepath + filename in exact case>$<start at byte (1=beginning of file)>|
	U>D: $FileLength <length of the requested file>|
	D>U: $Send|
	U>D: Data, in many chunks.
	D>U: $Send|       <- when 40906 bytes are sent, ask for more
	

<Introduction / Contents>

Client to Server Login

When first logging in, the client creates a socket connection. The server sends,

$Lock <lock> Pk=<pk>
$HubName <hubname>

The client must then respond with,

$Key <key>
$ValidateNick <nick>

If <nick> is already in use or is otherwise not accepted, the server must send,

$ValidateDenide

It really is $ValidateDenide, not $ValidateDenied. In this case, the client must send $ValidateNick again. Otherwise, the nick is accepted. The server may then send,

$GetPass

to which the client must reply,

$MyPass <password>

If the password is accepted and the user is an Op, the server must send,

$LogedIn
It really is $LogedIn, not $LoggedIn. If the user is not an Op, $LogedIn is skipped.
If the password is not accepted, the server must send,
$BadPass

and close the connection. NMDC hub answers with $HubIsFull even before the nickname is sent. Other hub implementations usually wait until the nickname is validated and then decide whether to let the user in or to disconnect him.
If no password is required or the server accepts the password, the server must finally send,

$Hello <nick>

The user is now logged in.


Download Example:

	Client <-> Server Communication in DC. 01-26-2003. By Sid
	---------------------------------------------------------- 

	Client Hub Login Example
	---------------------- 
	C = client
	H = hub 

	C>H: Connection
	H>C: $Lock <lock> Pk=<pk>|
	H>C: $HubName <hubname>|
	C>H: $Key <key>|$ValidateNick <nick>|
	C>H: $MyINFO $ALL <nick> <interest>$ $<speed>$<e-mail>$<sharesize>$
	C>H: $GetINFO <othernick> <nick>
	C>H: $GetINFO...
	

<Introduction / Contents>

Server to Hub Registration Server Communication

When first logging in, the server creates a socket connection. The hub registration server sends,

The server must then respond with,


Hub Registration Example:

	Server <-> Hub Registration Server Communication in DC. 04-29-2003. By Sid
	---------------------------------------------------------- 

	Hublist Registration
	---------------------- 
	R = hub registration server
	H = hub 

	H>R: Connection
	R>H: $Lock <lock> Pk=<pk>|
	H>R: $Key <key>|<hubname>|<hubaddress[:hubport]>|<hubdescription>|<hubusers>|<hubshare>|
R>H: Connection Closed

<Introduction / Contents>

Command Types (client to client)

Direct Connect uses TCP and UDP for client to client communication.
Normaly the client listen at port 412 for client connections, but if the port already in use it uses 413,414 and so on..
The following section describes the format of the Commands, Each field is denoted with < >.
The fields in the command are separated by a single space character (ASCII 32).
And each Command ends with a | (pipe). All Commands are case sensitive.

$GetListLen

The downloading client sends the $GetListLen to request the filesize of the remote DCList in bytes.

The uploading client responds to the $GetListLen command with $ListLen.

$MaxedOut

The $MaxedOut command is sent when there are no freeslots available from the uploading user.

$Error

The $Error command is sent when an error occurs, like file not found.

$Get

The $Get command is used to request a file from the uploading client.

$FileLength

The $FileLength is sent in response to the $Get command.

$Canceled

The $Canceled command is sent by eather party signifying that the download has been canceled prematurly.

UDP Client To Client Commands

The following commands are the Client To Client UDP Commands.

$SR

The $SR command is sent in response to a client searching. This is sent UDP when the searching client is in Active Mode.

<searchresponse> is made up of

Note: $SR is the only command that does not end in a "|".

$Ping

I'm not sure what the purpose of this command.


<Introduction / Contents>

Command Types (client to server)

Direct Connect uses TCP for client to server communication.
The following section describes the format of the Commands, Each field is denoted with < >.
The fields in the command are separated by a single space character (ASCII 32).
And each Command ends with a | (pipe). All Commands are case sensitive.

$Hello

Shortly after a new user, <nick> logs in, the server must send,

This indicates <nick> has logged in. If the new user is an operator, the server must additionally send a $OpList command to all users (documented at $GetNickList).

Each client should add <nick> to its list of hub users and, if $OpList is also received, update its list of operators. The new client must reply:

$GetNickList

To obtain a list of other users' nicks, the client may send,

to which the server must reply,

If a client receives a $OpList command listing its own nick, it should enable the "Redirect User" and "Kick" functions.

$MyINFO (Client to Server)

Shortly after logging in, the client must send,

The max size of the description is chosen by the hub implementation. (see $ValidateNick in Client to Server Login)
NOTE: some hub implementations do not consider a client to be in a logged in state before it has sent a $MyINFO. this is the correct behaviour, and the NMDC hub is flawed in this respect.

The server must pass this message to all users of the hub, including the sender. The client is expected to send this again if the information changes. SX says that the last byte of the speed is selected from the ascii values of 1 for normal, 2 for away, 3 also for away, 4 for fileserver, 5 also for fileserver, 6 for fileserver away, 7 also for fileserver away, 8 for fireball, 9 also for fireball, 10 for fireball away, and 11 also for fireball away.

$GetINFO

To obtain detailed information about a specific user, the client may send,

The server must respond with exactly the $MyINFO command sent by <othernick> to the server. I don't know what to do if <othernick> has not sent a $MyINFO command (perhaps he would have never been listed in $GetNickList, in which case the command could be rejected). I don't know what to do if <othernick> doesn't exist.

$ConnectToMe

The client may send $ConnectToMe to cause a peer to initiate a peer-to-peer connection for the purpose of transfering data.

The server sends this message unaltered to <remotenick>. <remotenick> must open a TCP connection to <senderIp>:<senderPort>.

$MultiConnectToMe

The client may send this instead of the $ConnectToMe to cause a peer on another hub to initiate a peer-to-peer connection for the purpose of transfering data. This is an extension for multiple hubs, which I'm not worried about yet.

$RevConnectToMe

A passive client may send this to cause a peer to send a $ConnectToMe back.

The server must send this message unmodified to <remoteNick>. If <remoteNick> is an active client, it must send a $ConnectToMe to <nick>. If not, it will reply with $RevConnectToMe. The clients will no longer connect to each other because they are both in passive mode.

$To

The client may send $To to send a private message to a peer.

The server must pass the message unmodified to client <othernick> which must display the message to the user.

< >

The client may send < > to send a public chat message to all hub users.

The server must pass the message unmodified to all other clients including <nick>.

$Quit

The hub should send $Quit to all users in the hub to let them know the users has disconnected.

The client must then close the socket. The server must send this message to all users when it is received from a client, or when a client connection is lost. Each client should remove <nick> from its list of hub users.

$OpForceMove

An op may send a $OpForceMove to cause a client to move to a different server.

On receiving this, the server must send to <victimNick>,

In addition to displaying the message, <victimNick> must disconnect from the server and connect to <newIp>. The server should not disconnect the client. I'm not sure if the client should send $Quit or if it should simply close the socket.

$Kick

Ops may send $Kick to cause the hub to disconnect a user.

The server must disconnect <victimNick>. The user is notified with the $To command.

$Search - Active clients

Clients are either "active", indicating they are on the Internet and can receive data directly from peers, or "passive", in which case they can communicate only through the existing connection to the server. To perform a search, an active client can send,

<searchstring> is made up of

The server must forward this message unmodified to all the other users. Every other user with one or more matching files must send one UDP packet to <clientip>:<clientport> for each match containing just the message,

<searchresponse> is made up of

Note: When the client sends the $SR command to the server it adds <ClientsNick> to the end of <searchresponse>.

$Search - Passive clients

To search the network for files matching a search term, a passive client may send,

The server must forward this message unmodified to all the other users. Every other user with one or more matching files must send to the server,

The server must pass the $SR message unmodified to <searchingNick>.

$MultiSearch

This is takes the same parameters as $Search (both active and passive) and behaves exactly as $Search, except the hub must additionally pass the search request to the other hubs in the cluster using the hub-to-hub $Search command.

$SR - Passive search result

Replies to passive search requests are sent through the server. Compare the $SR in Command Types (client to client).

<searchresponse> is made up of

The search result should be forwarded to <searchnick>, but without the <searchnick> at the end.

<Introduction / Contents>

Command Types (server to server)

Direct Connect uses UDP for server to server communication.
The following section describes the format of the Commands. Each field is denoted with < >.
The fields in the command are separated by a single space character (ASCII 32).
And each Command ends with a | (pipe). All Commands are case sensitive.

$Up

This message will be sent to each linked server.

The server receiving the $Up command must then respond with

$Search

Clients are either "active", indicating they are on the Internet and can receive data directly from peers, or "passive", in which case they can communicate only through the existing connection to the server. To perform a search, an active client can send,

<searchstring> is made up of

$ConnectToMe

This message sends the server to each linked server, when a user sends the $MultiConnectToMe message.


<Introduction / Contents>

Command Types (Experimental)

The fallowing commands are experimental and many have not been implemented yet. I feel that these commands are required to combat the level of fake sharing on the network.
The following section describes the format of the Commands, Each field is denoted with < >.
The fields in the command are separated by a single space character (ASCII 32).
And each Command ends with a | (pipe). All Commands are case sensitive.

$MyINFO

This is a modified version of the $MyINFO command that I feel will be useful.

$Supports BZList

This command is currently supported by DC++ to notify the downloading client that a BZList is available if their are no free slots.

Currently this command is only sent in the Client to Client communication and is sent by the client that is being connected to immediately after the $Lock command.

To improve apon this design I belive that this command should be refined in its use. For instance, if this command is sent the client should send a BZList regardless of the free slots status. The old style DCLst should only be sent if the client does not support BZLists.


Introduction / Contents>

Appendix A: Converting a Lock into a Key

As part of the initial negotiation between the client and hub, the hub sends a $Lock <lock> Pk=<pk> command and the client must respond with a $Key <key> command. Until the DCN encoding, which we'll discuss last, the <key> has exactly as many characters as the <lock>.

Except for the first, each key character is computed from the corresponding lock character and the one before it. If the first character has index 0 and the lock has a length of len then:


for (i = 1; i < len; i++)
	key[i] = lock[i] xor lock[i-1];

The first key character is calculated from the first lock character and the last two lock characters:


key[0] = lock[0] xor lock[len-1] xor lock[len-2] xor 5

Next, every character in the key must be nibble-swapped:


for (i = 0; i < len; i++)
	key[i] = ((key[i]<<4) & 240) | ((key[i]>>4) & 15)

Finally, the characters with the decimal ASCII values of 0, 5, 36, 96, 124, and 126 cannot be sent to the server. Each character with this value must be substituted with the string /%DCN000%/, /%DCN005%/, /%DCN036%/, /%DCN096%/, /%DCN124%/, or /%DCN126%/, respectively. The resulting string is the key to be sent to the server.

If your programming language of choice doesn't have xor or shift operations on characters, convert them to integers. If it doesn't have a bit shift at all, then x << y = x*(2**y) and x >> y = x/(2**y) for all integers x and y (** is the exponent operation or "to the power of"). Be sure to use unsigned values everywhere and do not do sign extension. Shift operations always lose the high or low bit (they are not roll operations!). The & (and) and | (or) operations are all logical, not boolean (eg. 6 & 13 = 4, not 1).

When the hub connects to the hublist, it must undergo a similar Lock/Key negotiation. The <key> calculation is the same, but the special number 5 in the second step is replaced with the following value is not computed from the hub's listening port, but rather the random outgoing port that the winsock selects. localport:

((localport>>8) + (localport & 255)) & 255


<Introduction / Contents>

Appendix B: Creating a Lock

Creating a Lock is much easier than decoding one. There are only a few things to keep in mind when creating a Lock.

First the Lock should be between 80 and 134 ascii characters long but it does not have to be.

Second the Pk should always be 16 ascii characters long but like the lock this is just a suggested length.

Third the characters with the decimal ASCII values of 0, 5, 36, 96, 124, and 126 must be substituted with the string
/%DCN000%/, /%DCN005%/, /%DCN036%/, /%DCN096%/, /%DCN124%/, or /%DCN126%/, respectively.

First we must create the actual Lock you can use random ascii characters for this.

for(int i = 0; i < RandLenOfLock; i++)
{
	lock[i] = (char)(94.0 * Math.random() + 33);
}

Now that the lock has been created lets create our Pk. Because there are so many Direct Connect clients popping up its probably a good idea to include your client type and version instead of a random Pk.

for(int i = 0; i < 16; i++)
{
	pk[i] = (char)(94.0 * Math.random() + 33);
}

There you go now all you have to do is send the data using the correct syntax.