Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

MyDC.ru _ Технические вопросы по PtokaX _ Анализ ответа от PtokaX

Автор: Sergey2009 23.2.2010, 0:45

Здравствуйте, пишу программу под C#, цель - это получить данные от хаба (в частности количество юзеров, размер шары). Для этого поставил PtokaX - чисто для анализа команд посылаемых моей программой. В программе создаю объект сокета и подсоединяюсь по протоколу (TCP/UDP) к указаному мною IP и порту, после посылки любой команды в окне администратора PtokaX выплывает такое: [00:02] x User removed: <unknown> (Socket 536). Я подозреваю, что необходимо предварительно "представиться" cерверу, но все попытки не успешны. Подскажите, чем подобные ответы сервера могут быть вызваны?

Точнее даже при обычном коннекте в админке PtockaX выдает [00:41] x User removed: <unknown> (Socket 524)

Автор: Setuper 23.2.2010, 1:02

Изучай протокол: http://mydc.ru/topic915.html

Автор: Sergey2009 23.2.2010, 1:05

У меня есть этот топик, запросы подобно этому: $Lock EXTENDEDPROTOCOL[некий_ключ_хаба] Pk=PtokaX не воспринимаются

Автор: mariner 23.2.2010, 11:24

http://mydc.ru/index.html?showtopic=1459&view=findpost&p=11029

Думаю вам сюда

Автор: Sergey2009 23.2.2010, 12:13

Cпасибо, я связался с человеком, может подскажет...

Автор: dmvn 23.2.2010, 12:35

Цитата(Sergey2009 @ 23.2.2010, 12:13) *
Cпасибо, я связался с человеком, может подскажет...

Помнится, я тоже сталкивался с этим. Как отлаживал - уже точно не помню, единственное что помню - так это то, что вставлял отладочную печать в код самого PtokaX (в nix-версию).
где-то тут на форуме были исходники маленькой проги HubLink для линковки хабов, которую я когда-то делал. Сравните вашу процедуру соединения и то что написано там.
Может быть мне удастся вспомнить, где там были грабли...

Но вообще когда он пишет User removed - это значит что он не получил нужного ответа (AFAIK). А вот что конкретно ему не понравилось - без отладки мне тогда понять не удалось. А дырявая башка уже всё забыла big_smile.gif Если у меня сохранился отладочный код - выложу...


Автор: Sergey2009 23.2.2010, 12:45

2 dmvn

Здравствуйте, ХабЛин программку глянул (она правда на С++), в моем конкретном случае, я создаю объект СОКЕТ. И конечную точку (Ip:Port). Протокол для соединения либо TCP, либо UDP...дак вот, к моему локальному хабу коннектится, но через некоторое время (команды я никакие не отсылаю), в птоке пишет [12:40] x User removed: <unknown> (Socket 536), а в Админке: Accepted Connectio - прибавляется 1, ну т.е. Соединение идет, а через некоторое время выкидывает меня (Сlosed Connection - прибавляется 1). Я подозреваю, что нужно в этот момент получить/отправить данные (т.е. в момент данного промежутка соединения)

В том-то и вопрос, как реагирует ПТОха на мою попытку? Если при соединеии он запрашивает данные Мол Кто я такой? Или же ему само соединение (в частности используемый протокол (TCP/UDP)) не нравится

Автор: Setuper 23.2.2010, 12:56

В протоколе же чётко описаны все шаги входа на хаб. Нужно только внимательно прочитать.

  1. Мы соединяемся с хабом (не отсылаем при соединении ничего, а ждём ответа от хаба).
  2. Хаб принимает наше соединение и отсылает нам команду $Lock.
  3. Мы должны отослать в ответ команду $Key и команду $ValidateNick.
  4. Хаб отправит нам команды $HubName и $Hello
  5. Мы должны отправить команды $Version, $GetNickList и $MyINFO
  6. Хаб отправит нам список пользователей.
  7. Всё, мы вошли на хаб.


Кроме всего прочего, для того чтобы находится на хабе нам нужно время от времени отсылать на хаб команду пинга (пустую команду - команду, состоящую только из одного разделителя протокола | ).

Автор: Sergey2009 23.2.2010, 13:03

Цитата(Setuper @ 23.2.2010, 14:56) *
В протоколе же чётко описаны все шаги входа на хаб. Нужно только внимательно прочитать.

  1. Мы соединяемся с хабом (не отсылаем при соединении ничего, а ждём ответа от хаба).
  2. Хаб принимает наше соединение и отсылает нам команду $Lock.
  3. Мы должны отослать в ответ команду $Key и команду $ValidateNick.
  4. Хаб отправит нам команды $HubName и $Hello
  5. Мы должны отправить команды $Version, $GetNickList и $MyINFO
  6. Хаб отправит нам список пользователей.
  7. Всё, мы вошли на хаб.


Кроме всего прочего, для того чтобы находится на хабе нам нужно время от времени отсылать на хаб команду пинга (пустую команду - команду, состоящую только из одного разделителя протокола | ).



1. Мы соединяемся с хабом (не отсылаем при соединении ничего, а ждём ответа от хаба).

Ну как бы соединение не получается, закрывает он мою попытку. Попытка рубится не сразу, а через некоторое время...и как я вижу по потоку, он (Хаб) ничего мне не отсылает. Может есть программы, что-то типа снифера, чтобы глянуть пакеты идущие от хаба мне?

Автор: Setuper 23.2.2010, 13:15

Ну раз не получается соединиться, то смотри причину в ошибке сокета.
Я так понимаю используется winsock? Соединение нужно устанавливать исключительно по протоколу TCP, никаких UDP!

Цитата
и как я вижу по потоку, он (Хаб) ничего мне не отсылает.

по какому ещё потоку? Лови то что тебе прислал хаб функцией recv.

Автор: Sergey2009 23.2.2010, 13:29

Объект (С#):
Socket Sock = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Тут впринципе все понятно, endpoint - cоздает конечную точку вида Ip:Protocol

Похоже подцепил ответ от хаба:

"$Lock EXTENDEDPROTOCOLe=nHlsuM`EX[SVsG2tbw1TXlcxAwin Pk=PtokaX|"
Это и есть ключ, теперь его нужно обратно отослать :-)...так

Цитата(Sergey2009 @ 23.2.2010, 15:28) *
Объект (С#):
Socket Sock = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Тут впринципе все понятно, endpoint - cоздает конечную точку вида Ip:Protocol

Похоже подцепил ответ от хаба:

"$Lock EXTENDEDPROTOCOLe=nHlsuM`EX[SVsG2tbw1TXlcxAwin Pk=PtokaX|"
Это и есть ключ, теперь его нужно обратно отослать :-)...так


Класс сокет, он создает свой поток

Автор: Setuper 23.2.2010, 13:32

Ну вот. Хаб тебе отсылал, а ты просто видимо не ловил то, что он тебе отсылал.
Хаб отсылает тебе $Lock и ждёт от тебя $Key, а ты молчишь, поэтому хаб закрывает с тобой соединение через некоторое время ожидания.

Автор: Sergey2009 23.2.2010, 13:40

Видите в чем дело, я ловил конструкцией :

byte[] remdata = { };
Sock.Receive(remdata);

Сокет - это Объект класса...и поидее он должен был подцепить данные от хаба. Хотя не ловил. Оказывается, необходимо действовать по такому:
http://mydc.ru/r/?http://krez0n.org.ua/archives/41

Кстати ответ от хаба идет в кодировки ASCII, хотя в документации к протоколу ADC написано : The protocol requires that all text must be sent as UTF-8 encoded Unicode, normalized in form C.


Я немного не понимаю, как свзяан TCP и ADC ?

Автор: Setuper 23.2.2010, 13:49

А при чём тут вообще ADC?
Хаб PtokaX работает на NMDC протоколе. Это разные протоколы.
А TCP - это сетевой протокол, который нужен для передачи данных по сети. А уже эти данные содержат в себе NMDC протокол.

Вообще, как так можно что-то писать, не разобравшись даже для чего нужен TCP протокол?))))

Автор: Sergey2009 23.2.2010, 15:14

>>PtokaX работает на NMDC.

Ок, понял :-)
Cпасибо за помощь, вы сюда загляните еще попозже:-)

Ловлю $Lock:

$Lock EXTENDEDPROTOCOL\\3xL@dKO:xJ3Aepet=d\\PG905pGwin Pk=PtokaX|

Т.е. ключ как я понимаю будет такой:

$Key \\3xL@dKO:xJ3Aepet=d\\PG905pGwin|

Соединение:

[15:18] <unknown> (ip) > $Key ?raUyUbfx3dl@ye0YSvAGtK]ncDwin|
[15:18] x User removed: <unknown> (Socket 444)


Однако, если посмотреть "обычное" рукопожатие внешнего клиента и хаба, то ключ (он конечно же другой) выглядит так:

$Key tСА° A С±±АА0rCЃ'Ђ·бv–ЕГуSв0BCҐ·/%DCN096%/’‘сW·бp|

Кодировка как я понимаю не ASCII и что за последовательность tСА° - ? она постоянно присутсвует в ключе других юзеров

Автор: Nickolya 23.2.2010, 15:35

Скорее всего такая последовательность есть всегда ввиду того что строка Lock содержит в себе всегда в начале EXTENDEDPROTOCOL
Алгоритм создания ключа можешь найти в описании протокола на этом форуме. Еще я знаю что хабы порой не проверяют ответ клиента, но это лишь слухи big_smile.gif

Автор: Setuper 23.2.2010, 15:43

Ключ нужно рассчитывать по параметру команды $Lock, а не тупо отправлять параметр команды $Lock!
Алгоритм расчёта ключа опять же смотри в протоколе: http://mydc.ru/ipb.html?act=findpost&pid=19477

Кроме этого, вместе с ключом нужно сразу же отослать и команду $ValidateNick.

Код
$Key[рассчитанный_по_параметру_команды_lock_ключ]|$ValidateNick nick|

Автор: Sergey2009 23.2.2010, 15:48

Спасибо, но мне нужно всего лишь кодировку в которой необходимо пересылать этот ключ обратно ПтоКе. Ведь принятая команда $Lock - уже содержит зашифрованную последовательность (tСА° < ключ> бp|). Я это к тому, что в моем ответе ПтоКе содержится на конце win|, и ключ отсылается в кодировке ACSII, а внешние клиенты шлют ключ как-то иначе

Автор: Setuper 23.2.2010, 15:52

Команда $Lock не содержит ключа.
Она содержит лишь код, по которому нужно по известному алгоритму определить ключ.

Код
$Lock [код]|
$Key lock2key([код])|


где lock2key - это функция (алгоритм), которая преобразует код команды lock в ключ

Автор: Sergey2009 23.2.2010, 16:08

А сам алгоритм lock2key есть, а то я давно С++ не пользовал.

Автор: Setuper 23.2.2010, 16:22

http://mydc.ru/topic2989.html

Автор: Sergey2009 23.2.2010, 16:26

Точно :-) Спасибо Вам, с наступающим (вшим) Праздником.

Ну если будут еще вопросы к вам....то уж пожалуйста стерпите :-)

Автор: Nickolya 23.2.2010, 16:27

http://mydc.ru/index.html?showtopic=915&view=findpost&p=19477

Автор: Setuper 23.2.2010, 16:32

Только не забудь добавить функцию DCN экранирования (см. последний пост указанной темы).

Автор: Sergey2009 24.2.2010, 2:35

>>Только не забудь добавить функцию DCN экранирования (см. последний пост указанной темы).

Функцию наlock2key С# (данную в топике) дополнил, но все таки что-то не то...Такого шаблона не получается:($Key tСА ° < ключ> бp|). Символы начала и конца последовательности tСА ° и бp| у меня не присутствуют и я даже не могу понять что это за дополнения. Мне кажется. я что-то не то передаю в функцию lock2key. Какой именно код нужно "шифровать", я так полагаю что код в последовательности вида
$Lock EXTENDEDPROTOCOLCVJYYYNNgSg:9J9ubJcBg4KKNhFwin Pk=PtokaX| , такой
EXTENDEDPROTOCOLCVJYYYNNgSg:9J9ubJcBg4KKNhFwin ... или я опять что-то упустил

Автор: Setuper 24.2.2010, 12:36

в функцию lock2key передавать нужно весь параметр команды $Lock

Автор: Sergey2009 24.2.2010, 12:40

Цитата(Setuper @ 24.2.2010, 14:36) *
в функцию lock2key передавать нужно весь параметр команды $Lock


Да я уж по разному пробовал...а эту функцию кто-нибудь проверял?

Автор: Setuper 24.2.2010, 12:48

если в параметре команды $Lock есть подстрока " Pk=", то нужно взять подстроку до " Pk=", в противном случае если есть пробел, то взять подстроку до пробела, иначе взять полностью весь параметр.

Автор: Sergey2009 24.2.2010, 13:08

См. файл

 

Автор: Setuper 24.2.2010, 13:31

Ну что тут можно сказать... Где-то ты наврал в коде. Ты получаешь неправильный ключ.
Вот я получил по твоему параметру lock правильный ключ.



разбирайся где у тебя там ошибка.

Автор: Sergey2009 24.2.2010, 13:36

Это не я в коде наврал, а функция Lock2Key не возвращает то, что нужно. Я и спрашиваю, функцию Lock2Key на С# кто-нибудь проверял?

Автор: Setuper 24.2.2010, 13:40

Я её не проверял. Я надеялся, что Markiz проверил, прежде чем публиковать в теме http://mydc.ru/topic2989.html
Видимо он накосячил с этой функцией.

Автор: Sergey2009 24.2.2010, 13:41

Блин ((

Автор: Setuper 24.2.2010, 13:45

Ща я попробую написать её под С#, хоть и не владею синтаксисом данного языка.

Автор: Sergey2009 24.2.2010, 13:52

Я могу с экранами переслать тебе

Вот это отсутвует в функции C#:

for(i = 0; i < len; ++i) key[i] = ((key[i]<<4) & 0xF0) | ((key[i]>>4) & 0x0F); char *newkey = (char *)calloc(1, len + 100);

Это смещение как я понял


<<4 - это сдвиг влево поразрядно, в Шарпе аналогичная операция
& 0x0F - фактически это и есть кодировка, в Шарпе так же

Автор: Setuper 24.2.2010, 13:59

Код
private string lock2key(string lock)
{
  int len = lock.Length;
  byte[] key = new byte[len];
  int i;
  for(i = 1; i < len; ++i)
    key[i] = (byte)(lock[i] ^ lock[i - 1]);
  key[0] = (byte)(lock[0] ^ lock[len - 1] ^ lock[len - 2] ^ 5);

  for(i = 1; i < len; ++i)
    key[i] = (byte)((key[i]<<4) & 0xF0) | ((key[i]>>4) & 0x0F);

  // тут ещё нужно сделать DCN экранирование

  return Encoding.ASCII.GetString(key);
}


По поводу DCN экранирования.

Экранируемые коды(символы): 0 (\0), 5(\5), 36($), 96(`), 124(|), 126(~)

То есть, вместо каждого нулевого символа в ключ нужно вставить строку "/%DCN000%/"
Вместо 5-го ANSI символа нужно вставить строку "/%DCN005%/"
Символ $ в ключе заменяем на "/%DCN036%/"
Символ ` в ключе заменяем на "/%DCN096%/"
Символ | в ключе заменяем на "/%DCN124%/"
Символ ~ в ключе заменяем на "/%DCN126%/"

Не знаю как в шарпе ты это будешь делать, в с/c++ это можно было сделать, например, функцией sprintf.

Автор: Sergey2009 24.2.2010, 14:20

Экран у меня сделан, сейчас допроверю ответ функции

Вот тут поправит нужно:

for(i = 1; i < len; ++i)
key[i] = ((key[i]<<4) & 0xF0) | ((key[i]>>4) & 0x0F);


На

for(i = 0; i < len; ++i)
key[i] = (byte)(((key[i]<<4) & 0xF0) | ((key[i]>>4) & 0x0F));

хмм...чего-то не хватает

Автор: Setuper 24.2.2010, 14:40

Чего не хватает?

Автор: Sergey2009 24.2.2010, 14:49

Цитата(Setuper @ 24.2.2010, 16:40) *
Чего не хватает?

Видишь в чем дело, мне кажется теряются разряды при явном преобразовании в размерный тип (byte) ... функция все равно возвращает не верное значение

Автор: Sergey2009 24.2.2010, 16:33

Все ОК, проблемма в кодировке была (не ASCII, Маркизу нужно стукнуть по голове :-)). Выкладываю рабочую функцию...могу сделать отдельным классом.



CODE
//
// Функция lock2key (влючает экранирование)
// принимает строку $Lock
//
// Cимволы команд $Lock и $Key с кодами 0, 5, 36, 96, 124 и 126 должны быть заменены,
// соответственно, на /%DCN000%/, /%DCN005%/, /%DCN036%/, /%DCN096%/, /%DCN124%/ и /%DCN126%/
// Экранируемые коды(символы):
// 0 (\0), 5(\5), 36($), 96(`), 124(|), 126(~)
// 0x0 0x5 0x24 0x60 0x7C 0x7E
private string lock2key(string str_lock)
{


byte[] arr_key = new byte[str_lock.Length];
int sL = str_lock.Length;
for (int i = 1; i < sL; ++i)
arr_key[i] = (byte)(str_lock[i] ^ str_lock[i - 1]);
arr_key[0] = (byte)(str_lock[0] ^ str_lock[sL - 1] ^ str_lock[sL - 2] ^ 5);

for (int i = 0; i < sL; ++i)
arr_key[i] = (byte)(((arr_key[i] << 4) & 0xF0) | ((arr_key[i] >> 4) & 0x0F));

string arr_keyTemp = Encoding.Default.GetString(arr_key);
for (int i = 0; i < sL; i++)
{
if (arr_keyTemp[i] == 0x0) { arr_keyTemp = arr_keyTemp.Substring(0, i) + "/%DCN000%/" + arr_keyTemp.Substring(i + 1, (arr_keyTemp.Length - (i + 1))); }
if (arr_keyTemp[i] == 0x5) { arr_keyTemp = arr_keyTemp.Substring(0, i) + "/%DCN005%/" + arr_keyTemp.Substring(i + 1, (arr_keyTemp.Length - (i + 1))); }
if (arr_keyTemp[i] == 0x24) { arr_keyTemp = arr_keyTemp.Substring(0, i) + "/%DCN036%/" + arr_keyTemp.Substring(i + 1, (arr_keyTemp.Length - (i + 1))); }
if (arr_keyTemp[i] == 0x60) { arr_keyTemp = arr_keyTemp.Substring(0, i) + "/%DCN096%/" + arr_keyTemp.Substring(i + 1, (arr_keyTemp.Length - (i + 1))); }
if (arr_keyTemp[i] == 0x7C) { arr_keyTemp = arr_keyTemp.Substring(0, i) + "/%DCN124%/" + arr_keyTemp.Substring(i + 1, (arr_keyTemp.Length - ( i+ 1))); }
if (arr_keyTemp[i] == 0x7E) { arr_keyTemp = arr_keyTemp.Substring(0, i) + "/%DCN126%/" + arr_keyTemp.Substring(i + 1, (arr_keyTemp.Length - (i + 1))); }
}

return arr_keyTemp;

}


Эм, чего-то не читабельно получилось

Всем спасибо еще раз, на хаб заходит...ник появляется и все ОК вообщем big_smile.gif

Автор: Setuper 24.2.2010, 16:42

Немного привёл к человеческому виду эту функцию:

Код
private static string lock2key(string Lock)
{
  int i, len = Lock.Length;
  byte[] key = new byte[len];
  for(i = 1; i < len; ++i)
    key[i] = (byte)(Lock[i] ^ Lock[i - 1]);
  key[0] = (byte)(Lock[0] ^ Lock[len - 1] ^ Lock[len - 2] ^ 5);

  for(i = 0; i < len; ++i)
    key[i] = (byte)(((key[i] << 4) & 0xF0) | ((key[i] >> 4) & 0x0F));

  string Buf = "", Key = Encoding.Default.GetString(key);
  for(i = 0; i < len; ++i)
  switch((int)Key[i]) {
    case 0:
    case 5:
    case 36:
    case 96:
    case 124:
    case 126:
      Buf += String.Format("/%DCN{0:000}%/", (int)Key[i]);
      break;
    default:
      Buf += Key[i];
      break;
  }
  return Buf;
}


В описание протокола добавлю эту реализацию на языке C#.

Автор: dmvn 18.3.2011, 2:52

Цитата(Sergey2009 @ 23.2.2010, 16:08) *
А сам алгоритм lock2key есть, а то я давно С++ не пользовал.


ну, как я понял, с протоколом вам тут подсказали уже.
насчёт lock2key - возьмите мою реализацию из HubLink - на C# почти так же всё пишется...