(2016-08-22 14:20:48 отредактировано aloch)

Две версии API в одной DLL

Добрый день!
Наше приложение защищается через API, автозащита не используется (например, потому, что приложение должно работать и без ключа, получив лицензию от Web-сервера или вообще работать в режиме без защиты).
Сотрудничаем с Guardant давно, начинали еще с Fidusов. Новые ключи (Sign, Code, Time) не используем т.к. их функциональность нам не нужна, покупаем, как старые клиенты, Stealth II и его сетевой вариант. Поэтому сидели на API 5 версии и соответственно использовали сервер 5-версии.
Все было хорошо, пока один из клиентов не обратился к нам с просьбой реализовать поддержку 7 сервера – у них все виртуализировано, железка для проброса USB одна, она подключена к виртуалке, где живут все их серверы ключей. Там уже стоит сервер 7, т.к. есть приложение, требующее именно эту версию сервера. Поставить 5 сервер вместе с 7 на один компьютер невозможно (вот интересно, почему?), 7 сервер не виден из приложения, защищенного 5 версией API, покупать вторую железку для проброса и заводить еще одну виртуалку клиент, естественно не хочет. В общем вот такая совместимость версий.
Пересобрать приложение с новой версией API не проблема, но в этом случае старые клиенты, использующие 5 версию сервера после обновления (а приложение довольно часто обновляется) просто не смогут подключиться к серверам, завалят нас вопросами и не будут счастливы от перспективы писать запросы в IT-отделы об обновлении сервера, и получить возможность работать дней через 10, пока там вся бюрократия сработает.
В общем появилось желание собрать программу с ОБОИМИ версиями API. Все обращения к API происходят из DLL, написанной на C++. DLL линкуется с GrdFWMC.obj, использовать DLL-версию API не хочется (мне кажется, слишком легко ее подменить). Слинковать приложение с GrdFWMC.obj 5 версии одновременно с GrdFWMC.obj 7 версии не получается. Заводить отдельную новую DLL для 5 версии API и линковать старую DLL с 7 версией не хочется, т.к. лень напрягаться над тем, как передать из этой новой DLL информацию о найденном ключе каким-то скрытым образом (иначе ее также легко подменят).
В итоге я в простом текстовом редакторе (FAR) поменял имена функций Guardant API в GrdFWMC.obj 5 версии, а сам файл переименовал в GrdFWMC_v5_renamed.obj. Переименовал вот так:
016 00036DD6 SECT1  notype ()    External     | _Gr5SetWorkMode@12
051 0003F756 SECT1  notype ()    External     | _ns5FindNext@4
073 000402B6 SECT1  notype ()    External     | _nn5Check@4
Т.е. заменил префикс _Grd на _Gr5, _nsk на _ns5 и _nnk на _nn5.
После этого DLL стала успешно линковаться c GrdFWMC.obj 7 версии и GrdFWMC_v5_renamed.obj.
После этого я внес соответствующие исправления в GrdAPI_v5_renamed.h и при тестировании убедился, что DLL успешно обращается (в зависимости от задаваемой в настройках опции) к 5 или к 7 версии API и находит соответственно сервера 5 и 7 версии.
Конечно, перед обращением к 5 версии вызывается Shutdown для 7 версии и наоборот. Только GrdDllMain() и Gr5DllMain остаются вызванными одновременно все время жизни приложения.
В общем, все работает, но конечно есть вопрос поводу возможных проблем с таким одновременным использованием двух версий API в одной DLL. Хотелось бы услышать ответ от разработчиков защиты, но не в духе «мы это не поддерживаем».
Ну и в конце хочется сказать по поводу совместимости. Это очень важный момент для любого ПО – в том числе и для Вашего. За все время мы купили у Вас 1700 ключей, и вот делать нам и нашим клиентам больше нечего, как разруливать несовместимости версий чужого ПО.
Очень бы хотелось в качестве обеспечения совместимости получить возможность использовать обе версии сервера 5 и 7 на одном компьютере (что там сложного?) или работу 7 сервера в режиме совместимости с 5 версией ПО.
С уважением,
Алексей

Re: Две версии API в одной DLL

Здравствуйте, aloch.

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

Что же касается отсутствия обратной совместимости современных версий сервера сетевых ключей со "старым" API и автозащитой (далее просто - обратная совместимость), то эта мера в большей степени вынужденная и определенно не очень безболезненная для всех. Дело в частности в том, что поддерживать и дорабатывать движок сервера 5.хх версий в определенный момент стало нецелесообразным, поскольку стабильность его работы обещала быть уже неподобающей, на что влияло и появление новых версий ОС Windows (начиная с версии 8). Еще, например, вырисовывалась потенциальная необходимость в поддержке IPv6 и все более нарастающая необходимость в портировании сервера под Linux.

В купе вышеописанные требования и ряд иных причин послужили стимулом для разработки полностью нового движка для сервера сетевых ключей и в мае 2012 года сервер на новом движке был выпущен вместе с релизом Guardant SDK 6.1. Сервер для ОС семейства Linux появился в составе SDK 7.1. На сегодняшний день современная версия сервера сетевых ключей является куда более надежной и актуальной заменой 5.хх версий, но, к сожалению, реализация обратной совмести могла серьезно ухудшить качество его работы и осложнить дальнейшее развитие и доработки.

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

Re: Две версии API в одной DLL

Спасибо за ответ. Будем жить вот так, с галочкой в настройках, не самое плохое решение :)

Про два сервера на одном хосте я сам потом понял, что делить ключи между ними нужно будет.

Что бы хотелось Вам предложить для облегчения "нашей жизни"

Сделать сборки объектных и заголовочных файлов 5 АПИ с переименованными функциями доступными для загрузки с сайта, а решение с использованием двух версий АПИ в одном процессе поддерживаемым официально. Старые версии сервера будут еще очень долго использоваться, как мне кажется просто по принципу - работает, не трогай.

Сейчас в случае несовместимости сервера и клиента (даже в рамках одной версии АПИ) приходит сообщение об ошибке "Сервер не найден" (при этом в 5 версии его видит монитор), что делает весьма сложной выявление причины такого поведения. Было бы хорошо ввести ошибку "Сервер ключа несовместим с клиентом".

С уважением,

Алексей

Re: Две версии API в одной DLL

aloch пишет:

Старые версии сервера будут еще очень долго использоваться, как мне кажется просто по принципу - работает, не трогай.

Да, наверняка так и есть)
Еще раз спасибо за отклики, ваши предложения переданы в отдел разработки.