Widevine 会话更新无限循环
Widevine Session Update endless Loop
我正在使用 chrome 中的 libwidevinecdm.so
来处理受 DRM 保护的数据。我目前正在成功设置从许可证服务器获得的 widevine 服务器证书。我还可以使用我尝试解码的媒体的 pssh 框创建会话。到目前为止一切都成功了(所有的承诺都很好地解决了)。
(会话是这样创建的:_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
消息,而没有返回。这是否意味着我的反应是错误的?或者这是别的东西?
Br
亚尼克
这个问题是由于 CreateSessionAndGenerateRequest
中的所有内容都是同步完成的 - 这意味着到 CreateSessionAndGenerateRequest
returns 你的承诺将永远得到解决。
CDM 将在 CreateSessionAndGenerateRequest
中发出 kLicenseRequest
,它不会以 "fire & forget" 的方式发出,但该函数会在那里等待,直到您从 cdm::Host_10::OnSessionMessage
。由于我的 OnSessionMessage
实现是在调用 UpdateSession
之前创建一个到许可证服务器的同步 HTTP 请求 - 也是同步的 - 整个链最终被阻塞。
所以最终我在调用 UpdateSession
的同时仍然在 CreateSessionAndGenerateRequest
中并且我假设 CDM 无法处理这个并且通过使用给定 ID 创建一个新会话并再次生成请求来做出反应,这当然触发了另一个UpdateSession
等等。
最终打破循环的最简单方法是制作一些异步的东西。我决定在收到 kLicenseRequest
时启动一个单独的线程,等待几毫秒以确保 CreateSessionAndGenerateRequest
有时间完成(不确定是否真的需要),然后向许可证发出请求服务器。
我唯一要做的改变就是添加周围的 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();
}
我正在使用 chrome 中的 libwidevinecdm.so
来处理受 DRM 保护的数据。我目前正在成功设置从许可证服务器获得的 widevine 服务器证书。我还可以使用我尝试解码的媒体的 pssh 框创建会话。到目前为止一切都成功了(所有的承诺都很好地解决了)。
(会话是这样创建的:_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
消息,而没有返回。这是否意味着我的反应是错误的?或者这是别的东西?
Br 亚尼克
这个问题是由于 CreateSessionAndGenerateRequest
中的所有内容都是同步完成的 - 这意味着到 CreateSessionAndGenerateRequest
returns 你的承诺将永远得到解决。
CDM 将在 CreateSessionAndGenerateRequest
中发出 kLicenseRequest
,它不会以 "fire & forget" 的方式发出,但该函数会在那里等待,直到您从 cdm::Host_10::OnSessionMessage
。由于我的 OnSessionMessage
实现是在调用 UpdateSession
之前创建一个到许可证服务器的同步 HTTP 请求 - 也是同步的 - 整个链最终被阻塞。
所以最终我在调用 UpdateSession
的同时仍然在 CreateSessionAndGenerateRequest
中并且我假设 CDM 无法处理这个并且通过使用给定 ID 创建一个新会话并再次生成请求来做出反应,这当然触发了另一个UpdateSession
等等。
最终打破循环的最简单方法是制作一些异步的东西。我决定在收到 kLicenseRequest
时启动一个单独的线程,等待几毫秒以确保 CreateSessionAndGenerateRequest
有时间完成(不确定是否真的需要),然后向许可证发出请求服务器。
我唯一要做的改变就是添加周围的 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();
}