Skip to content

Commit

Permalink
For C++
Browse files Browse the repository at this point in the history
- Add key rotation option.
- Add custom exception
  • Loading branch information
Jason239 committed Sep 21, 2023
1 parent 901a9fd commit 63e948c
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 12 deletions.
52 changes: 43 additions & 9 deletions cpp/PallyConCpixClient/CpixClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace pallycon {
LPBYTE bytePtr = Base64Decode(buffer, outputLength);
if (bytePtr == NULL)
{
throw std::exception("base64Decode() Failed!");
throw CpixClientException("base64Decode() Failed!");
}
std::shared_ptr<BYTE> smartPtr(bytePtr, std::default_delete<BYTE[]>());
return smartPtr;
Expand Down Expand Up @@ -92,7 +92,7 @@ namespace pallycon {
{
}

std::string CpixClient::GetRequestData(std::string contentId, DrmType drmType, EncryptionScheme encryptionScheme, TrackType trackType)
std::string CpixClient::GetRequestData(std::string contentId, DrmType drmType, EncryptionScheme encryptionScheme, TrackType trackType, long periodIndex)
{
_keyMap.clear();
std::string requestData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
Expand Down Expand Up @@ -128,8 +128,11 @@ namespace pallycon {
reqRoot.addAttribute("xmlns:speke", "urn:aws:amazon:com:speke");

XMLNode reqContentKeyList = reqRoot.addChild("cpix:ContentKeyList");
XMLNode reqContentKeyUsageRuleList = reqRoot.addChild("cpix:ContentKeyUsageRuleList");
XMLNode reqDRMList = reqRoot.addChild("cpix:DRMSystemList");
XMLNode reqContentKeyUsageRuleList = reqRoot.addChild("cpix:ContentKeyUsageRuleList");
XMLNode reqContentKeyPeriodList;
if(periodIndex > 0)
reqContentKeyPeriodList = reqRoot.addChild("cpix:ContentKeyPeriodList");

for (auto& map : _keyMap)
{
Expand All @@ -141,6 +144,21 @@ namespace pallycon {
reqContentKeyUsageRule.addAttribute("intendedTrackType", map.first.c_str());
reqContentKeyUsageRule.addAttribute("kid", map.second.c_str());

if (periodIndex > 0)
{
std::string keyPeriodId = "keyPeriod_";
char randomUuid[UUID_SIZE_INCLUDING_NULL_CHAR];
__GenerateUUID(randomUuid);
keyPeriodId.append(randomUuid);

XMLNode reqContentKeyPeriod = reqContentKeyPeriodList.addChild("cpix:ContentKeyPeriod");
reqContentKeyPeriod.addAttribute("id", keyPeriodId.c_str());
reqContentKeyPeriod.addAttribute("index", std::to_string(periodIndex).c_str());

XMLNode reqKeyPeriodFilter = reqContentKeyUsageRule.addChild("cpix:KeyPeriodFilter");
reqKeyPeriodFilter.addAttribute("periodId", keyPeriodId.c_str());
}

if (drmType & WIDEVINE)
{
XMLNode reqWidevineNode = reqDRMList.addChild("cpix:DRMSystem");
Expand Down Expand Up @@ -196,11 +214,11 @@ namespace pallycon {
{
std::string errMsg;
errMsg = "CpixClient::parseResponse() : Response parsing failed. Response body: \n" + responseBody;
throw std::runtime_error(errMsg);
throw CpixClientException(errMsg);
}

if (responseRoot.getAttribute("id") == NULL)
throw std::runtime_error("CpixClient::parseResponse() : No CID in response.");
throw CpixClientException("CpixClient::parseResponse() : No CID in response.");

packInfo.contentId = responseRoot.getAttribute("id");

Expand Down Expand Up @@ -228,6 +246,21 @@ namespace pallycon {
drmInfo.trackType = resTrackType;
drmInfo.keyId = keyId;

XMLNode resKeyPeriodFilter = resContentKeyUsageRule.getChildNode("cpix:KeyPeriodFilter", 0);
if (!resKeyPeriodFilter.isEmpty())
{
XMLCSTR resPeriodId = resKeyPeriodFilter.getAttribute("periodId");
XMLNode resContentKeyPeriodList = responseRoot.getChildNode("cpix:ContentKeyPeriodList");
for (int i = 0; i < resContentKeyPeriodList.nChildNode(); i++)
{
XMLNode resContentKeyPeriod = resContentKeyPeriodList.getChildNode("cpix:ContentKeyPeriod", i);
if (0 == strcmp(resPeriodId, resContentKeyPeriod.getAttribute("id")))
{
drmInfo.periodIndex = resContentKeyPeriod.getAttribute("index");
}
}
}

XMLNode resContentKey;
for (int i = 0; i < resContentKeyList.nChildNode(); i++)
{
Expand Down Expand Up @@ -322,23 +355,24 @@ namespace pallycon {
return packInfo;
}

ContentPackagingInfo CpixClient::GetContentKeyInfoFromPallyConKMS(const std::string contentId, DrmType drmType, EncryptionScheme encryptionScheme, TrackType trackType)
ContentPackagingInfo CpixClient::GetContentKeyInfoFromPallyConKMS(const std::string contentId
, DrmType drmType, EncryptionScheme encryptionScheme, TrackType trackType, long periodIndex)
{
if (contentId.empty())
{
throw std::runtime_error("CpixClient::getContentPackagingInfoFromKmsServer() : invalid parameter.");
throw CpixClientException("CpixClient::getContentPackagingInfoFromKmsServer() : invalid parameter.");
}

std::shared_ptr<CurlHttpRequester> httpRequester(new CurlHttpRequester());
CpixRequester client(_kmsUrl, _encToken, httpRequester);
_lastRequestRowData = GetRequestData(contentId, drmType, encryptionScheme, trackType);
_lastRequestRowData = GetRequestData(contentId, drmType, encryptionScheme, trackType, periodIndex);
client.SetRequestData(_lastRequestRowData);
std::string responseRowData = client.Request();
if (responseRowData == "")
{
_lastRequestStatus = httpRequester->getRequestStatus();
std::string errorMessage = "CpixRequester:request() : " + httpRequester->getReason();
throw std::exception(errorMessage.c_str());
throw CpixClientException(errorMessage.c_str());
}
_lastResponseRowData = responseRowData;

Expand Down
7 changes: 5 additions & 2 deletions cpp/PallyConCpixClient/CpixClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <string>
#include <map>
#include <vector>
#include "CpixClientException.h"

namespace pallycon
{
Expand Down Expand Up @@ -96,6 +97,7 @@ namespace pallycon
std::string key;
std::string keyId;
std::string iv;
std::string periodIndex;
std::string widevinePSSH;
std::string widevinePSSHpayload;
std::string playreadyPSSH;
Expand Down Expand Up @@ -124,7 +126,7 @@ namespace pallycon

std::map<std::string, std::string> _keyMap;

std::string GetRequestData(std::string contentId, DrmType drmType, EncryptionScheme encryptionScheme, TrackType trackType);
std::string GetRequestData(std::string contentId, DrmType drmType, EncryptionScheme encryptionScheme, TrackType trackType, long periodIndex);
ContentPackagingInfo ParseResponse(const std::string& responseBody);

public:
Expand Down Expand Up @@ -167,8 +169,9 @@ namespace pallycon
* @param encryptionScheme Encryption scheme. (e.g. CENC, CBCS, etc)
* @param trackType Track type for multi-key packaging. (e.g. SD|HD|AUDIO)
* For single-key packaging, it should be ALL_TRACKS.
* @param periodIndex Period index for key rotation.
*/
ContentPackagingInfo GetContentKeyInfoFromPallyConKMS(const std::string contentId, DrmType drmType, EncryptionScheme encryptionScheme = CENC, TrackType trackType = ALL_TRACKS);
ContentPackagingInfo GetContentKeyInfoFromPallyConKMS(const std::string contentId, DrmType drmType, EncryptionScheme encryptionScheme = CENC, TrackType trackType = ALL_TRACKS, long periodIndex = 0);
};
}

7 changes: 7 additions & 0 deletions cpp/PallyConCpixClient/CpixClientException.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "CpixClientException.h"

namespace pallycon {
CpixClientException::CpixClientException(const std::string& msg) : message(msg) {}
CpixClientException::~CpixClientException() throw() {}
const char* CpixClientException::what() { return (this->message).c_str(); }
}
18 changes: 18 additions & 0 deletions cpp/PallyConCpixClient/CpixClientException.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include <exception>
#include <string>

namespace pallycon {
class CpixClientException : public std::exception
{
private:
std::string message;

public:
CpixClientException(const std::string& msg);
~CpixClientException() throw();
const char* what();
};
}

2 changes: 2 additions & 0 deletions cpp/PallyConCpixClient/PallyConCpixClient.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CpixClientException.cpp" />
<ClCompile Include="CpixRequester.cpp" />
<ClCompile Include="CpixClient.cpp" />
<ClCompile Include="curlHttpException.cpp" />
Expand All @@ -30,6 +31,7 @@
<ClCompile Include="util.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="CpixClientException.h" />
<ClInclude Include="CpixRequester.h" />
<ClInclude Include="CpixClient.h" />
<ClInclude Include="curlHttpException.h" />
Expand Down
2 changes: 2 additions & 0 deletions cpp/PallyConCpixClient/PallyConCpixClient.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<ClCompile Include="Helper\xmlParser.cpp">
<Filter>helper</Filter>
</ClCompile>
<ClCompile Include="CpixClientException.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="CpixRequester.h" />
Expand All @@ -36,6 +37,7 @@
<ClInclude Include="Helper\json\json.h">
<Filter>helper\json</Filter>
</ClInclude>
<ClInclude Include="CpixClientException.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="helper">
Expand Down
5 changes: 5 additions & 0 deletions cpp/PallyConCpixClientSample/PallyConCpixClientSample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "helper/base64.h"
#include "helper/json/json.h"
#include "CpixClient.h"
#include "CpixClientException.h"

#if defined(_WIN32)
FILE _iob[] = { *stdin, *stdout, *stderr };
Expand Down Expand Up @@ -152,6 +153,10 @@ int main()
outFile << strJson << std::endl;
outFile.close();
}
catch (pallycon::CpixClientException& e)
{
std::cout << "CpixClientException : " << e.what() << std::endl;
}
catch (std::exception& e)
{
std::cout << "Exception : " << e.what() << std::endl;
Expand Down
4 changes: 3 additions & 1 deletion cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@
* @param trackType Track type for multi-key packaging. (e.g. SD|HD|AUDIO)
* For single-key packaging, it should be ALL_TRACKS.
*/
ContentPackagingInfo GetContentKeyInfosFromPallyConKMS(const std::string cid, DrmType drmType, EncryptionScheme encryptionScheme = CENC, TrackType trackType = ALL_TRACKS);
ContentPackagingInfo GetContentKeyInfosFromPallyConKMS(const std::string cid, DrmType drmType, EncryptionScheme encryptionScheme = CENC, TrackType trackType = ALL_TRACKS, long periodIndex = 0);
```
***EncryptionScheme*** and ***TrackType*** are optional parameters that default to `CENC` and `ALL_TRACKS`(single-key) when nothing is entered.
If you want to enable key rotation, you can put a value greater than 0 in `periodIndex` which defaults to 0.
```c++
Expand Down

0 comments on commit 63e948c

Please sign in to comment.