Обновление Widevine Session бесконечный цикл - PullRequest
1 голос
/ 09 января 2020

Я использую libwidevinecdm.so из chrome для обработки данных, защищенных DRM. В настоящее время я успешно устанавливаю сертификат сервера Widevine, полученный с сервера лицензий. Я также могу создать сеанс с полем ps sh носителя, который я пытаюсь декодировать. Пока все успешно (все обещания разрешаются нормально).

(сеанс создается следующим образом: _cdm->CreateSessionAndGenerateRequest(promise_id, cdm::SessionType::kTemporary, cdm::InitDataType::kCenc, pssh_box.data(), static_cast<uint32_t>(pssh_box.size()));)

Затем я получаю сообщение сеанса типа kLicenseRequest, которым я являюсь пересылка на соответствующий сервер лицензий. Сервер лицензий отвечает правильным ответом и тем же объемом данных, который я вижу в браузере при использовании Chrome. Затем я передаю это на мою сессию так:

        _cdm->UpdateSession(promise_id, session_id.data(), static_cast<uint32_t>(session_id.size()),
                            license_response.data(), static_cast<uint32_t>(license_response.size()));

Проблема сейчас в том, что это обещание никогда не разрешится. Он продолжает публиковать сообщение kLicenseRequest снова и снова в моем сеансе, даже не возвращаясь. Значит ли это, что мой ответ неверный? Или это что-то еще?

Бр Яник

1 Ответ

0 голосов
/ 11 января 2020

Проблема вызвана тем фактом, что все в CreateSessionAndGenerateRequest выполняется синхронно - это означает, что к тому времени, когда CreateSessionAndGenerateRequest вернет ваше обещание, оно будет всегда разрешено.

МЧР выпустит kLicenseRequest внутри CreateSessionAndGenerateRequest, и он не делает это в режиме "запусти и забудь", но функция ждет там, пока ты не вернешься из cdm::Host_10::OnSessionMessage. Поскольку моя реализация OnSessionMessage создавала синхронный HTTP-запрос к серверу лицензий до - также синхронно - вызова UpdateSession, вся цепочка оказалась блокированной.

Так что в конечном итоге я звонил UpdateSession все еще находясь внутри CreateSessionAndGenerateRequest, и я предполагаю, что CDM не может справиться с этим и реагирует, создавая новый сеанс с данным ID и снова генерируя запрос, который, конечно, вызвал еще один UpdateSession и т. д.

В конечном счете, самым простым способом разорвать цикл было сделать что-то асинхронное. Я решил запустить отдельный поток при получении kLicenseRequest, подождать несколько миллисекунд, чтобы убедиться, что CreateSessionAndGenerateRequest успевает завершить sh (не уверен, действительно ли это требуется), а затем отправить запрос на сервер лицензий. .

Единственное изменение, которое я должен был сделать, это добавить окружение std::thread:

    void WidevineSession::forward_license_request(const std::vector<uint8_t> &data) {
        std::thread{
                [=]() {
                    std::this_thread::sleep_for(std::chrono::milliseconds{100});

                    net::HttpRequest request{"POST", _license_server_url};
                    request.add_header("Authorization", fmt::format("Bearer {}", _access_token))
                            .byte_body(data);

                    const auto response = _client.execute(request);
                    if (response.status_code() != 200) {
                        log->error("Widevine license request not accepted by license server: {} {} ({})", response.status_code(), response.status_text(), utils::bytes_to_utf8(response.body()));
                        throw std::runtime_error{"Error requesting widevine license"};
                    }

                    log->info("Successfully requested widevine license from license server");
                    _adapter->update_session(this, _session_id, response.body());
                }
        }.detach();
    }
...