myDC.ru

Здравствуйте, гость ( Вход | Регистрация )

 
История благодарностей участнику Enyby. Спасибо сказали: 239
Дата поста: В теме: За сообщение: Спасибо сказали:
20.8.2010, 13:00 Хаблисты
Итак, по порядку.

Как было справделиво замеченно, можно отсекать по команде не MyINFO, после MyINFO, но не все тут гладко.
Можно довольно долго висеть на хабе из 5 человек ожидая другой команды.

Вообще говоря, по протоколу, список MyINFO, должен заканчиваться MyINFO хаблиста, но, к сожалению, так поступают не все хабы.

Дальше. Есть такое расширение протокола как Zon. Которое предполагает сжатие gzip дл передаваемых данных. проблема состоит в том, что некоторые хабы в любом случае включат это сжатие не смотря поддерживается оно клиентом или нет. Эта команда может появляться где угодно и, обычно, список пользователей передается в сжатом виде, что означает, что ее нужно игнорировать и не разрывать соединение, так как процесс входа на хаб может быть не завершен.

Также следует отслеживать команды ValidateDenide и ForceMove. Первая означает что ник занят или не является допустимым, а вторая - дает редирект, при переполнении или других причинах. Четкой команды, свидетельствующей о бане не существует, обычно это сообщение от бота со словом ban, но не обязательно.

100% алгоритма определения окончания инициализации не существует или мне он не известен. Пользуюсь набором правил следующего вида:
  1. Если получены команды Quit или Search - вход завершен.
  2. Если получена команда OpList и перед этим была получена хоть одна команда MyINFO - вход завершен. Некоторые хабы, отсылают список операторов ранее списка пользователей, хотя это и не соответствует протоколу.
  3. Если было зафиксировано получение команд MyINFO, а после этого пришла команда не Zon и не MyINFO - вход завершен.


Как вариант, можно еще пытаться отлавливать MOTD, но оно может отсылаться в ЛС.

По поводу дубликатов, проблема решается просто, все это дело заноситься в ассциативный массив по ключу ника, а потом из массива и считается шара и число пользователей. Также необходимо отслеживать свой ник и его игнорировать.

Еще. Хаб может не поддерживать BotINFO/HubINFO, тогда с текущим алгоритмом вы будете ждать вечность команды HubINFO. Чтобы этого не произошло, необходимо, после указания поддержки данных команд в отсылаемом Supports, проверить наличие поддержи в полученном Supports.
dro
20.8.2010, 1:38 Хаблисты
Пингом - быстрей, но пинг предоставляет недостаточно информации. С другой стороны, он виден админу, и если часто пинговать, то вас попросту забанят. Поэтому у меня раз в 5 минут хаблист заходит как клиент и раз в час - как пингер, т. е. каждый 12 раз из тех, что по 5 минут.

В целом пингер неплох.
Критика по коду:
  1. Соблюдайте отступы, намного приятнее будет читать. Для этих целей лучше пользоваться IDE с автоформатированием кода, например, Eclipse.
  2. Лучше не использовать принудительное подавление @, а писать так, чтобы никаких ошибок не было.
  3. Код
    $myinfo = explode('$', $linie[$i]);
    @$share = $share + $myinfo[6];

    У вас нет никаких гарантий что в массиве 6 элементов. Целесобразнее:
    Код
    $myinfo = explode('$', $linie[$i]);
    if(isset($myinfo[6]))
    $share = $share + $myinfo[6];

  4. Код
    $useri = $useri + 1;

    Лучше писать через оператор ++.
  5. Код
    function lock2key($_LOCK, $port)

    Не тот алгоритм. Этот алгоритм для захода ХАБА на хаблист, а вам нужен обычный, в котором не порта. Да и порт вы не тот указали, вы указали порт подключения, а в этом алгоритме нужно указать локальный порт.


Чтобы бота пускали на все хабы, не нужно передавать специфический тэг клиента. Да и число хабов онлайн можно не 21 ставить. "H:21/0/1" - 21 хаб 1 и на одном админ.

UPD:
И да, я тут увидел зачатки работы как клиента (Подсчет MyINFO). Вам предстоит нетривиальная задача определения когда заканчивается процесс инициализации хаба. Также вам необходимо отсевать свой собственный MyINFO, так как он вносит погрешность в ваши измерения. В дополнение к этому есть скрипты манипулирующие MyINFO, из-за них оно может приходить несколько раз для одного пользователя, что вызовет искажение размера шары и числа пользователей.

Так что работы тут еще много.
dro
29.7.2010, 1:10 lock2key для hublist'а
Код для работы с хаблистом.
Итак, по порядку. Известно что хаблисты используют схему $Lock-$Key. Основная проблема заключаеться в том, что этот алгоритм чуть-чуть отличается от обычного. Если быть точным, ровно на первый байт.

В интернете видел информацию, что большинство хаблистов благополучно игнорируют правильность этого кода и есть там один, особо задиристый. Однако, чем черт не шутит. Поэтому наваял свою реализацию на PHP.

Но, буду последователен. Исходником послужил код из исходников PtokaX хаба:
Код
uint16_t lport =  (uint16_t)ntohs(addr.sin_port);
char cMagic = (char) ((lport&0xFF)+((lport>>8)&0xFF));

// strip the Lock data
char *temp;
if((temp = strchr(sBuffer+6, ' ')) != NULL) {
    temp[0] = '\0';
}

// Compute the key
memcpy(sMsg, "$Key ", 5);
sMsg[5] = '\0';
size_t iLen = temp-sBuffer;
char v;

// first make the crypting stuff
for(size_t i = 6; i < iLen; i++) {
    if(i == 6) {
        v = sBuffer[i] ^ sBuffer[iLen] ^ sBuffer[iLen-1] ^ cMagic;
    } else {
        v = sBuffer[i] ^ sBuffer[i-1];
    }

    // Swap nibbles (0xF0 = 11110000, 0x0F = 00001111)
    v = (char)(((v << 4) & 0xF0) | ((v >> 4) & 0x0F));

    switch(v) {
        case 0:
            strcat(sMsg, "/%DCN000%/");
            break;
        case 5:
            strcat(sMsg, "/%DCN005%/");
            break;
        case 36:
            strcat(sMsg, "/%DCN036%/");
            break;
        case 96:
            strcat(sMsg, "/%DCN096%/");
            break;
        case 124:
            strcat(sMsg, "/%DCN124%/");
            break;
        case 126:
            strcat(sMsg, "/%DCN126%/");
            break;
        default:
            strncat(sMsg, (char *)&v, 1);
            break;
    }
}

На старте задается lport как локальный порт хаба, в подключении к хаблисту. У хаблиста порт, естественно, 2501. У нас же, тот что назначит система, а значит случайный.
sBuffer - содержит исходный $Lock код. sMsg - по завершении будет содержать нужный $Key код.

Теперь собственно код на PHP:
Код
function lock2key($_LOCK, $port)
{
    $lockLength = strlen($_LOCK);

    $LockToKey = '';

    for ($j = 0; $j < strlen($_LOCK); $j++)
    {
        if($j == 0) {
            $h = ord($_LOCK{0}) ^ 0 ^ ord( $_LOCK{ $lockLength - 1} ) ^ ($port % 256 + ($port>>8) % 256);
        }
        else {
            $h = ord($_LOCK{$j}) ^ ord($_LOCK{$j-1});
        }

        $h = $h % 256;

        $a = (($h<<4) & 240) | (($h>>4) & 15);

        if($a == '126' or $a == '124' or $a == '96' or $a == '36' or $a == '5' or $a == '0') {
            $LockToKey .= "/%DCN";

              if ($a < 100) $LockToKey .= "0";
              if ($a < 10) $LockToKey .= "0";

              $LockToKey .= $a;
              $LockToKey .= "%/";
        }
        else {
              $LockToKey .= chr($a);
        }
    }
    return $LockToKey;
}

Из заметных отличий от стандартного следующие:
Код
$h = ord($_LOCK{0}) ^ 0 ^ ord( $_LOCK{ $lockLength - 1} ) ^ ($port % 256 + ($port>>8) % 256);

Используется связка первого символа с нулем (вместо последнего символа), а затем с последним символом (вместо предпоследнего). Также, вместо константы 5, используется магический байт вычисляемый как сумма верхнего и нижнего байта шестнадцетиричного представления номера порта.
Все остальные "отличия" - экономия "на спичках" + изменения форматирования, не меняющие алгоритма работы.
Функция принимает два параметра, строку $Lock и номер порта.

Было бы неплохо этот код обосновать в соответствующей теме, описания протокола.
Nickolya, Setuper, Saymon21
20.4.2010, 17:34 Хаблисты
Полный код я давать не буду. Дам часть, только боюсь что он вырван из контекста и многое не будет понятно. К слову программу я определяю именно через $BotInfo, а шару через получение списка.

Код
case '$HubINFO':
                        $hubinfo = explode(' ', $linie[$i], 2);
                        $tmp = explode('$', $hubinfo[1]);
                        $hub['online'] = 2;
                        $hub['name'] = $tmp[0];
                        $hub['address'] = $tmp[1];
                        $hub['description'] = $tmp[2];
                        $hub['maxusers'] = $tmp[3];
                        $hub['minshare'] = $tmp[4];
                        $hub['minslots'] = $tmp[5];
                        $hub['maxhubs'] = $tmp[6];
                        $hub['type'] = $tmp[7];
                        $hub['admin'] = $tmp[8];

Код
                    case '$MyINFO':
                        $hub['MyINFO'] = true;
                        if ($user[2] != $hub['me']->nick) {
                            $tmp = explode('$', $linie[$i]);
                            if(!isset($hub['users'][$user[2]]))
                            $hub['share'] += $tmp[count($tmp) - 2];
                            $hub['users'][$user[2]] = '';
                        }
                        break;
Accelerator
4.11.2009, 15:18 Хаблисты
Код
<?php
function lock2key($_LOCK) {

    $lockLength = strlen ($_LOCK);

    $h = ord($_LOCK{0}) ^ ord( $_LOCK{ $lockLength - 1} ) ^ ord( $_LOCK{ $lockLength - 2} ) ^ 5;
    while ($h > 255) {$h = $h - 256;}

    $h = (($h<<4) & 240) | (($h>>4) & 15);

    $a = $h;

    if ($a == '126' || // '~'
    $a == '124' || // '|'
    $a == '96' || // '`'
    $a == '36' || // '$'
    $a == '5' || // '^E'
    $a == '0') // NUL
    {
        $LockToKey = "/%DCN";

        if ($a < 100)
        $LockToKey .="0";
        if ($a < 10)
        $LockToKey .="0";
        $LockToKey .= $a;
        $LockToKey .= "%/";
    } else {
        $LockToKey = chr ($a);
    }

    for ($j = 1; $j < strlen($_LOCK); $j++) {
        $h = ord($_LOCK{$j}) ^ ord($_LOCK{$j-1});

        while ($h > 255) {$h = $h - 256;}

        $h = (($h<<4) & 240) | (($h>>4) & 15);
        $a = $h;

        if ($a == '126' || // '~'
        $a == '124' || // '|'
        $a == '96' || // '`'
        $a == '36' || // '$'
        $a == '5' || // '^E'
        $a == '0') // NUL
        {
            $LockToKey .= "/%DCN";

            if ($a < 100)
            $LockToKey .="0";
            if ($a < 10)
            $LockToKey .="0";
            $LockToKey .= $a;
            $LockToKey .= "%/";
        } else {
            $LockToKey .= chr ($a);
        }
    }

    return $LockToKey;
}

function process($sock, $str) {
//    echo "A: ".$str.'|'.PHP_EOL;
    socket_send($sock, $str.'|', strlen($str) + 1, NULL);
}

function checkHub($address, $port) {
    $nick = substr(md5(mt_rand(0, 100000)), 0, 10);
    $description = substr(md5(mt_rand(0, 100000)), 0, 10);
    $email = substr(md5(mt_rand(0, 100000)), 0, 10);
    $sharesize = mt_rand(10*1024, 20*1024)*mt_rand(1024*1024,2*1024*1024);
    $status = new stdClass();

    if ($fp=@fsockopen(htmlentities($address, ENT_QUOTES),$port,$ERROR_NO,$ERROR_STR,5))
    {
        fclose($fp);
        $status->online = true;
        $status->users = 0;

        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if (!socket_connect($socket, gethostbyname($address), $port)) {
            echo 'Ошибка: '.socket_strerror(socket_last_error());
            return;
        }
        $end = '';
        while ($buffer = socket_read($socket, 2048, PHP_BINARY_READ)) {
            $linie = explode('|', $end.$buffer);
            $size = sizeof($linie);
            for ($i = 0; $i < $size; ++$i) {
                if ($i + 1 == $size) {
                    $end = $linie[$i];
                    break;
                }
                $user = explode(' ', $linie[$i]);
//                echo "Q: ".$linie[$i].PHP_EOL;                
                switch($user[0]) {
                    case '$Hello':
//                        echo "Q: ".$linie[$i].PHP_EOL;
                        if ($user[1] == $nick) {
                            process($socket, '$Version 1,0091');
                            process($socket, '$GetNickList');
                            process($socket, '$MyINFO $ALL '.$nick.' '.$description.'<++ V:0.674,M:A,H:1/0/1,S:20>$ $LAN(T3).$'.$email.'$'.$sharesize.'$');
                        }                        
                        break;
                    case '$HubTopic':
//                        echo "Q: ".$linie[$i].PHP_EOL;    
                        $tmp = explode(' ', $linie[$i], 2);
                        $status->topic = $tmp[1];                                                
                        break;
                    case '$HubName':
//                        echo "Q: ".$linie[$i].PHP_EOL;    
                        $hubinfo = explode(' ', $linie[$i], 2);
                        $tmp = explode(' - ', $hubinfo[1], 2);
                        $status->name = $tmp[0];
                        $status->topic = (count($tmp) > 1) ? $tmp[1] : '';                                            
                        break;
                    case '$Lock':
//                        echo "Q: ".$linie[$i].PHP_EOL;
//                        process($socket, '$Supports NoGetINFO NoHello UserIP2 ');
                        process($socket, '$Key '.lock2key($user[1]));
                        process($socket, '$ValidateNick '.$nick);
                        break;
                    case '$NickList':
//                        echo "Q: ".$linie[$i].PHP_EOL;
                        $tmp = explode(' ', $linie[$i], 2);
                        $nicks = explode('$$', $tmp[1]);
                        $status->users = count($nicks);                        
                        break 3;
                        break;
                    case '$MyINFO':    
//                        echo "Q: ".$linie[$i].PHP_EOL;                    
                        if ($user[2] != $nick) {
                            $status->users++;
                        }
                        else {
                            break 3;
                        }
                        break;
                    default:
//                        echo "Q: ".$linie[$i].PHP_EOL;
                        break;
                }
            }
        }
        socket_close($socket);
    }
    else {
        $status->online = false;
    }
    return $status;
}

Простейший пингер на php. По сути полноценный ДС клиент, обрезаный не хило. Интересует специфиакация общения хабпингер - хаб. Ибо после $BotINFO мне рвут соединение без какого-либо ответа.
Accelerator

5 страниц V  « < 3 4 5
RSS Сейчас: 19.4.2024, 20:10