--Расширения BruteNet-- Расширением BruteNet является пара динамических библиотек для серверной и клиентской части соответственно. Плагинный функционал ориентируется в основном на локальный перебор, при этом серверная часть, являясь абсолютно демократичной к ботам, отправляет одни и те же начальные сведения, необходимые для перебора. Архитектуру серверной в целом, а так же место участия расширений можно представить так: ______________ ________ ____________________ | | | | | | | пользователь | -> | плагин | -> | обслуживание ботов | |______________| |________| |____________________| Сначала, получив основные данные, такие как диапазон перебора, множество символов перебора, новые, дополнительные сведения берутся от указанного плагина для серверной части. То есть, плагин серверной части всего лишь запрашивает новые данные, и на этом его возможности ограничиваются. Это было сделано лишь с целью упрощения написания своих расширений для индвидуальных задач. Расширение на стороне бота выполняет более ключевую роль - непосредственный перебор. Прямой перебор ложится на руки разработчика плагина. Показательный пример для восстановления строки по md5-хэшу полностью открыт и поэтому трудностей для адаптацией под свои задачи возникнуть не должно. Работу клиентской части можно представить так : __________________________________ | | | коммуникация с сервером перебора | |__________________________________| ___________________________/ | | |получение данных о переборе| |___________________________| \___________________________________ | | | непосредственный перебор | |___________________________________| При этом, перебор и коммуникация с сервером ведется параллельно, поэтому данные, которые будут возвращаться плагином должны синхронизироваться с перебором. В пробном плагине показано как этого можно добиться, не снижая, при этом, производительности. --Строки перебора-- Любой перебор идет на своем множестве перебираемых символов (charset). Системе удобнее представлять строки как номер текущего символа в charset. Например, при charset="abc" строку "ccbc" будем представлять в виде "\x03\x03\x02\x03". --Описание dll-серверной части-- На C, С++: #define DLL __declspec( dllexport ) #define EXPORT __cdecl extern "C" { DLL void EXPORT GetV(char * title); DLL void * EXPORT Main(void * obj,int state); DLL int EXPORT GetMess(void * obj,int level,char * out); DLL int EXPORT UpdateMess(void * obj,int level,char * in_message,char * reply); DLL char * EXPORT GetPluginData(void * obj,short int * pLen); DLL int EXPORT GetNumMessP(void * obj); } Обратите внимание: функции должны экспортироваться по правилам c declaration (cdecl), это позволит не беспокоиться о написании расширений под, например, unix-подобные ОС не интересуясь работой основной серверной части. Теперь остановимся на непосредственном описании каждой функции: 1) void GetV(char * title) - при вызове должна записать свое уникальное имя в title. Таким образом мы можем идентифицировать плагин не волнуясь о реальном имени расширения как библиотеки. Зная имя title для данного плагина мы можем его указать при заполненении главной информации о переборе. 2) void * Main(void * obj, int state) - если значение state равно 0, товозвращает указатель на свою собственную структуру, работа с которой будет вестись самим плагином. Ведь мы в общем-то не имеем права использовать для данных пользователя глобальных переменных так как плагин загружается только один раз при загрузке системы. Если state отлично от 0, то структура по адресу obj должна будет освобождена. В дальнейшем указатель obj будет играть роль основного параметра для всех последующих функций. 3) int GetMess(void * obj, int level, char * out) - получение нового "вопроса" для пользователя. В случае с плагином md5 естественным будет вопрос о значении md5-слепка. level - целое, для первого вызова равно 0, для всех успешных последующих level+1 и так далее. out - указатель на буфер, гарантируется что возможна запись до 255 байт включительно. При успешном выполнении выполнение возвращается НЕ 0. 4) int UpdateMess(void * obj,int level,char * in_message,char * reply) - сохранение сообщения полученного от пользователя. Значение двух первых аргументов и возвращаемое значение см. GetMess(). in_message - указатель на строку введенную пользователем, reply - указатель на буфер результата, возвращаемого серверной части. Вы можете гарантированно писать 255 байт. Вы должны учитывать, что вызов UpdateMess может быть не последователен, то есть Ваша реализация должна корректно работать для нескольких вызовов для одного level и т.п. 5) char* GetPluginData(void * obj,short int * pLen) - возвращает указатель на буфер, который будет передаваться плагину стоящему на бот-части системы. pLen - указатель на целое, длину буфера. 5) int GetNumMessP(void * obj) - возвращает общее количество "вопросов" пользователю. Очевидно, что level, поэтому может принимать значение от 0 до GetNumP-1. Пример реализации можно посмотреть в server/plugins/plugin.cpp --Описание dll бот-части-- На C, С++: #define DLL __declspec( dllexport ) #define EXPORT __cdecl extern "C" { DLL void EXPORT GetV(char * title); DLL int EXPORT GetWord(void * obj,char * r_word); DLL void EXPORT SetLastWord(void * obj,char * word); DLL void EXPORT StopBrute(void * obj); DLL int EXPORT StartBrute(void * obj,char * start_word,char * end_brute,char * charset, unsigned char power,char * plugin_data,unsigned short int plugin_data_length); DLL void * EXPORT Main(void * obj,int state); } Примечание: все буферы используемые в качестве значений строк перебора должны задаваться в описанном выше формате. 1) void GetV(char * title) - см. серверную часть. 2) void * Main(void * obj, int state) - см. серверную часть. 3) int StartBrute(...) - функция непосредственного перебора, начиная с позиции start_word до позиции end_brute. Множество символов учавствующих в переборе задается в буфере charset длины power. plugin_data и plugin_data_length буфер и его длина передаваемая главного сервера. Функция возвращает : 0 - заданный отрезок полностью отработан и поиск не привел к положительному результату 1 - строка найдена, ее можно получить вызовом GetWord() 2 - ошибка plugin-данных (plugin_data или plugin_data_length) 3) int GetWord(void * obj, char * r_word) - пишет в буфер r_word текущую строку перебора. Возвращается ее длина. 4) void SetLastWord(void * obj, char * word) - обязана установить новый предел перебора. Если он оказывается меньше текущего перебираемого слова, то StartBrute() должна завершить свою работу. Согласно описанной в первой части схеме, функции StartBrute(), GetWord(), SetLastWord() будут вызываться в разных потоках (threads), поэтому Вы должны следить за корректной синхронизацией разделяемых данных. Реализацию без снижения производительности можно посмотреть в расширении md5.