Управление входящими соединениями устройств

SberMobile Server обычно устанавливает исходящие соединения TCP/UDP с подключенными к сети устройствами, аутентифицируя себя с учетными данными, находящимися в учетной записи устройства. Однако некоторые устройства сами подключаются к серверу. Это в основном M2M устройства, подключаемые к IP сети через модемы GPRS/3G. Такие устройства не имеют статичных IP адресов и имен хоста, поэтому доступ сервера к ним невозможен.

Драйвера устройств, обслуживающие входящие соединения с устройствами, требуют специального подхода к их разработке:

  • Метод драйвера устройства globalInit() должен вызывать метод createGlobalConfigContext(Context rootContext, VariableDefinition... properties). Его параметры должны включать определение переменной, которая содержит настройки глобального подключения драйвера, т.е. хотя бы номер порта для прослушивания входящих соединений с устройствами.
  • Метод драйвера globalStart() должен открывать прослушивающий сокет и запускать отдельный поток, который принимает и обслуживает входящие соединения с устройствами. Этот метод имеет доступ к свойствам глобальной конфигурации драйвера путем получения контекста глобальных свойств через getGlobalConfigContext() и извлечения значения переменной глобальной конфигурации из этого контекста. Возможно (но не необходимо) создать класс, унаследованный из SocketServerThread (для нормальных сокетов) или SslSocketServerThread (для сокетов, защищенных SSL), и использовать этот класс в качестве потока прослушивания сокетов.
  • Вышеупомянутый поток сокетов сервера должен прерваться из метода драйвера globalStop().
  • Поток сокетов сервера должен принимать входящие соединения и создавать новый поток (поток контроллера соединений) для обслуживания каждого соединения. Например, неабстрактная реализация SocketServerThread или SslSocketServerThread должна включать метод createConnectionThread(), который создает поток контроллера входящих соединений каждый раз при подключении нового устройства к серверу.
  • Каждая учетная запись устройства должна в большинстве случаев определять уникальный идентификатор устройства (такой как код мобильного устройства IMEI) и пароль устройства, используемый для аутентификации и авторизации входящих соединений с устройствами. Переменная, содержащая эту информацию, должна добавляться к учетной записи устройства путем реализации метода setupDeviceContext().
  • Поток контроллера соединений должен сначала аутентифицировать и авторизовать устройство, используя родной протокол устройства для извлечения его уникального идентификатора, и найдя учетную запись устройства, соответствующую этому идентификатору, а также проверив, что пароль устройства соответствует паролю, определенному в настройках учетной записи устройства.
  • Как только устройство аутентифицируется и определяется соответствующая учетная запись (контекст) устройства сервера, поток контроллера устройства должен:
  • Получить экземпляр класса драйвера/плагина на устройство путем вызова deviceContext.getDriver().
  • Зарегистрировать данный контроллер устройства в экземпляре устройства для установления временных отношений между учетной записью/драйвером устройства и текущим входящим соединением, управляемым контроллером.
  • Вызвать deviceContext.requestSynchronization() для получения нормальной последовательности синхронизации.
  • Все "классические" методы драйвера должны выполнять ввод/вывод устройства через экземпляр контроллера устройства, зарегистрированного потоком контроллера входящих соединений. Однако входящие соединения вносят в этот процесс некоторые особенности:
  • Метод драйвера shouldSynchronize() должен вернуть true, если контроллер входящих соединений в данный момент зарегистрирован в экземпляре драйвера, в ином случае false.
  • Метод драйвера connect() должен отправлять устройству некоторые тестовые команды, чтобы убедиться, что входящее соединение все еще имеется. Если соединение TCP/UDP прервано или устройство не отвечает, метод соединения должен вызвать исключение для приостановки последующей синхронизации.
  • Метод драйвера disconnect() должен отключать контроллер входящих соединений и закрывать его входящие соединения.