Формирование сообщения рукопожатия

104
04 июля 2021, 22:10

На странице спецификации протокола BitTorrent, сказано, что сообщение рукопожатия, должно быть отправлено первым, после подключения. И указано следущяя структура этого сообщения:

Handshake

The handshake is a required message and must be the first message transmitted by the client. It is (49+len(pstr)) bytes long.

handshake: <pstrlen><pstr><reserved><info_hash><peer_id>
  • pstrlen: string length of , as a single raw byte

  • pstr: string identifier of the protocol

  • reserved: eight (8) reserved bytes. All current implementations use all zeroes. Each bit in these bytes can be used to change the behavior of the protocol. An email from Bram suggests that trailing bits should be used first, so that leading bits may be used to change the meaning of trailing bits.
  • info_hash: 20-byte SHA1 hash of the info key in the metainfo file. This is the same info_hash that is transmitted in tracker requests.
  • peer_id: 20-byte string used as a unique ID for the client. This is usually the same peer_id that is transmitted in tracker requests (but not always e.g. an anonymity option in Azureus).

Так вот, я подумал что сообщение должно формироваться следущим образом:

const string protocol = "BitTorrent protocol";
string request = $"<{protocol.Length}>" +           // <pstrlen>
                 $"<{protocol}>" +                  // <pstr>
                 "<        >" +                     // <reserved>
                 $"<{torrentFile.GetInfoHash()}>" + // <info_hash>
                 "<-AZ206088->";                    // <peer_id>

Однако это не работает, т.к. при отправке сообщения одному из пиров, он не отвечает, т.е. не шлет в ответ ничего, думаю я не правильно сформировал сообщение рукопожатия.

Как правильно сформировать сообщение?

Answer 1

Все строковые константы начисто скопированы из вопроса.

Судя по протоколу можно сделать так:

1) Получаем байты из строки протокола. В доках написано, что всё в ASCII

const string protocol = "BitTorrent protocol";
var content = Encoding.ASCII.GetBytes(protocol);

2) Создаём массив нужного размера

var message = new byte[49 + content.Length];

3) Записываем байтовую длину строки протокола

int currentPosition = 0;
message[currentPosition++] = (byte) content.Length;

3) Записываем само байтовое представление

Array.Copy(content, 0, message, currentPosition, content.Length);
currentPosition += content.Length;

4) Оставляем 8 пустых байт по воле доков с:

currentPosition += 8;

5) Копируем 20-байтовый хэш

Array.Copy(torrentfile.GetInfoHashBytes(), 0, message, currentPosition, 20);
urrentPosition += 20;

6) Получаем байтовое представление peer строки и записываем его
Если вы следуете Azureus-style, то у вас указан неверный peer, т.к. этот стиль подразумевает:

'-', two characters for client id, four ascii digits for version number, '-', followed by random numbers.

const string peer = "-AZ206088-";
var peerTextContent = Encoding.ASCII.GetBytes(peer);
Array.Copy(peerTextContent, 0, message, currentPosition, peerTextContent.Length);
currentPosition += peerTextContent.Length;

7) В протоколе сказано, что peer должен состоять ровно из 20 байт, и если не хватает, то заполнить случайными числами, а т.к. у нас нет лишних байт в массиве, то мы заполняем его до конца, т.к. это будет соответствовать тому, сколько байт не хватило в peer

new Random().NextBytes(message.AsSpan(currentPosition));

8) Отправляем наш массив message куда нужно :3

READ ALSO
Последовательность нажатия клавиш

Последовательность нажатия клавиш

Как выполнить открытие формы, после нажатия определенной последовательности клавиш (стрелок) на клавиатуре? Прошу предоставить пример кода,...

77
Задать авторазмер UserControl передаваемого в TabPage

Задать авторазмер UserControl передаваемого в TabPage

Есть отдельный UserControl, который я передаю в TabPage и юзаю его в TabControl

84
Множественное использование UserControl

Множественное использование UserControl

Работаю с WPF с применением паттерна MVVMСтолкнулся с проблемой, создал UserControl(далее UC) один общий который будет несколько раз использоваться:

123
Можно ли создать &ldquo;составную&rdquo; переменную в c#. Например состоящую из byte,byte,string,string

Можно ли создать “составную” переменную в c#. Например состоящую из byte,byte,string,string

Чтоб к каждому члену этого списка соотвецвовало 2 переменные byte и 2 string

109