О структуре команд
Все команды протокола начинаются с символа $. Исключение составляет команда сообщения чата, которая должна иметь следующую структуру:
При этом, данный синтаксис команды чата обязателен в направлении клиент —> хаб, в то время, как хаб может отсылать клиенту любые сообщения, не начинающиеся с символа $, и клиент должен воспринимать такие сообщения, как сообщения чата.
Символы-разделители протокола: $, | и пробел. Протокол не имеет экранирующих символов, поэтому для отсылки символов $ и | в параметрах команд нужно использовать их коды: $ и | Чтобы при обратной расшифровке $ не путался с настоящим $, в некоторых случаях амперсанды тоже экранируются в & Амперсаны экранируются, если амперсанд в сочетании с последующим текстом образует $ или | или & В остальных случаях апмерсанды не экранируются, но если это всё же сделать, большинство клиентов поймут это правильно. Никакие другие сущности в протоколе NMDC не используются. Например, амперсанды нельзя кодировать последовательностью &
Образцовый код экранирования сообщений можно подсмотреть в NmdcHub.cpp (в исходниках DC++):
string NmdcHub::validateMessage(string tmp, bool reverse) {
string::size_type i = 0;
if(reverse) {
while( (i = tmp.find("$", i)) != string::npos) {
tmp.replace(i, 5, "$");
i++;
}
i = 0;
while( (i = tmp.find("|", i)) != string::npos) {
tmp.replace(i, 6, "|");
i++;
}
i = 0;
while( (i = tmp.find("&", i)) != string::npos) {
tmp.replace(i, 5, "&");
i++;
}
} else {
i = 0;
while( (i = tmp.find("&", i)) != string::npos) {
tmp.replace(i, 1, "&");
i += 4;
}
i = 0;
while( (i = tmp.find("$", i)) != string::npos) {
tmp.replace(i, 1, "&");
i += 4;
}
i = 0;
while( (i = tmp.find("|", i)) != string::npos) {
tmp.replace(i, 1, "&");
i += 4;
}
i = 0;
while( (i = tmp.find('$', i)) != string::npos) {
tmp.replace(i, 1, "$");
i += 4;
}
i = 0;
while( (i = tmp.find('|', i)) != string::npos) {
tmp.replace(i, 1, "|");
i += 5;
}
}
return tmp;
}
Строка сообщения разделяется на команды по средствам символа |. Пример трёх команд, отосланных одной строкой:
Регистр команд имеет значение. Переводы строки отсылаются в стиле DOS (CR/LF, "\r\n")
И хаб, и клиент могут посылать друг другу keep–alive пустой командой: одиночный символ |
хаб <—> клиент
$BadPass
$Close
$ConnectToMe
$ForceMove
$GetINFO
$GetNickList
$GetPass
$Hello
$HubIsFull
$HubName
$HubTopic
$Key
$Kick
$Lock
$LogedIn
$MyINFO
$MyPass
$MultiConnectToMe
$MultiSearch
$NickList
$OpForceMove
$OpList
$Quit
$RevConnectToMe
$Search
$SR
$Supports
$To
$UserCommand
$UserIP
$Version
$ValidateNick
$ValidateDenide
клиент <—> клиент
хаб <—> хаб
$SR
$Up
$UpToo
хаб <—> хаблист
пингер <—> хаб
Команды характеристик
Разное
Известные характеристики
хаб <—> клиент
клиент <—> клиент
ADCGet
BZList
CHUNK
ClientID
GetCID
GetTestZBlock
GetZBlock
MiniSlots
TTHL
TTHF
XmlBZList
ZLIG
Вход на NMDC хаб
Основная статья: Последовательность входа на NMDC хаб
Регистрация в хаблисте
Основная статья: Последовательность действий хаба при регистрации в хаблисте
Вход на PtokaX хаб
Основная статья: Последовательность входа на хаб PtokaX
Вход на хаб HeX
Основная статья: Последовательность входа на хаб HeX