From 8a870286b517468f1da8492c8db1f026e4104de2 Mon Sep 17 00:00:00 2001 From: Michael Dietz Date: Wed, 7 Sep 2022 09:39:24 -0500 Subject: [PATCH 01/12] fix auth query template, used by signAwsRequestInfoQueryParam --- src/source/Common/AwsV4Signer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/source/Common/AwsV4Signer.h b/src/source/Common/AwsV4Signer.h index 951c7f068..71208e2da 100644 --- a/src/source/Common/AwsV4Signer.h +++ b/src/source/Common/AwsV4Signer.h @@ -51,14 +51,14 @@ extern "C" { #define AUTH_HEADER_TEMPLATE "%s Credential=%.*s/%s, SignedHeaders=%.*s, Signature=%s" // Authentication query template -#define AUTH_QUERY_TEMPLATE "&X-Amz-Algorithm=%s&X-Amz-Credential=%s&X-Amz-Date=%s&X-Amz-Expires=%u&X-Amz-SignedHeaders=%.*s" +#define AUTH_QUERY_TEMPLATE "?X-Amz-Algorithm=%s&X-Amz-Credential=%s&X-Amz-Date=%s&X-Amz-Expires=%u&X-Amz-SignedHeaders=%.*s" // Token query param template #define SECURITY_TOKEN_PARAM_TEMPLATE "&X-Amz-Security-Token=%s" // Authentication query template #define AUTH_QUERY_TEMPLATE_WITH_TOKEN \ - "&X-Amz-Algorithm=%s&X-Amz-Credential=%s&X-Amz-Date=%s&X-Amz-Expires=%u&X-Amz-SignedHeaders=%.*s" SECURITY_TOKEN_PARAM_TEMPLATE + "?X-Amz-Algorithm=%s&X-Amz-Credential=%s&X-Amz-Date=%s&X-Amz-Expires=%u&X-Amz-SignedHeaders=%.*s" SECURITY_TOKEN_PARAM_TEMPLATE // Signature query param template #define SIGNATURE_PARAM_TEMPLATE "&X-Amz-Signature=%s" From 220bffdf8b108ead592776d2853ccef78953cc56 Mon Sep 17 00:00:00 2001 From: Michael Dietz Date: Fri, 16 Sep 2022 12:57:26 -0500 Subject: [PATCH 02/12] aws service configurable for presigned urls, eg s3 --- .../amazonaws/kinesis/video/common/Include.h | 6 ++++ src/source/Common/AwsV4Signer.c | 29 ++++++++++++++----- src/source/Common/AwsV4Signer.h | 2 ++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/include/com/amazonaws/kinesis/video/common/Include.h b/src/include/com/amazonaws/kinesis/video/common/Include.h index d5e548792..a38a8e3e8 100644 --- a/src/include/com/amazonaws/kinesis/video/common/Include.h +++ b/src/include/com/amazonaws/kinesis/video/common/Include.h @@ -98,6 +98,11 @@ extern "C" { */ #define MAX_REGION_NAME_LEN 128 +/** + * Maximum allowed service name length + */ +#define MAX_SERVICE_NAME_LEN 128 + /** * Maximum allowed user agent string length */ @@ -483,6 +488,7 @@ struct __RequestInfo { //!< NOTE: The body will follow the main struct UINT32 bodySize; //!< Size of the body in bytes CHAR url[MAX_URI_CHAR_LEN + 1]; //!< The URL for the request + CHAR service[MAX_SERVICE_NAME_LEN + 1]; //!< The AWS service for the request CHAR certPath[MAX_PATH_LEN + 1]; //!< CA Certificate path to use - optional CHAR sslCertPath[MAX_PATH_LEN + 1]; //!< SSL Certificate file path to use - optional CHAR sslPrivateKeyPath[MAX_PATH_LEN + 1]; //!< SSL Certificate private key file path to use - optional diff --git a/src/source/Common/AwsV4Signer.c b/src/source/Common/AwsV4Signer.c index 3522b3dae..d47a5267b 100644 --- a/src/source/Common/AwsV4Signer.c +++ b/src/source/Common/AwsV4Signer.c @@ -73,7 +73,7 @@ STATUS generateAwsSigV4Signature(PRequestInfo pRequestInfo, PCHAR dateTimeStr, B hmacSize = SIZEOF(hmac); CHK_STATUS(generateRequestHmac((PBYTE) pScratchBuf, curSize, (PBYTE) dateTimeStr, SIGNATURE_DATE_STRING_LEN * SIZEOF(CHAR), hmac, &hmacSize)); CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) pRequestInfo->region, (UINT32) STRLEN(pRequestInfo->region), hmac, &hmacSize)); - CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) KINESIS_VIDEO_SERVICE_NAME, (UINT32) STRLEN(KINESIS_VIDEO_SERVICE_NAME), hmac, &hmacSize)); + CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) pRequestInfo->service, (UINT32) STRNLEN(pRequestInfo->service, MAX_SERVICE_NAME_LEN), hmac, &hmacSize)); CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) AWS_SIG_V4_SIGNATURE_END, (UINT32) STRLEN(AWS_SIG_V4_SIGNATURE_END), hmac, &hmacSize)); CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) pSignedStr, signedStrLen * SIZEOF(CHAR), hmac, &hmacSize)); @@ -117,6 +117,11 @@ STATUS signAwsRequestInfo(PRequestInfo pRequestInfo) CHK(pRequestInfo != NULL && pRequestInfo->pAwsCredentials != NULL, STATUS_NULL_ARG); + // signAwsRequestInfo is a public api function, if service is not specified default to "kinesisvideo" so no breaking changes are introduced to the api + if (pRequestInfo->service[0] == L'\0') { + STRNCPY(pRequestInfo->service, KINESIS_VIDEO_SERVICE_NAME, MAX_SERVICE_NAME_LEN); + } + // Generate the time CHK_STATUS(generateSignatureDateTime(pRequestInfo->currentTime, dateTimeStr)); @@ -167,6 +172,11 @@ STATUS signAwsRequestInfoQueryParam(PRequestInfo pRequestInfo) CHK(pRequestInfo != NULL && pRequestInfo->pAwsCredentials != NULL, STATUS_NULL_ARG); + // signAwsRequestInfoQueryParam is a public api function, if service is not specified default to "kinesisvideo" so no breaking changes are introduced to the api + if (pRequestInfo->service[0] == L'\0') { + STRNCPY(pRequestInfo->service, KINESIS_VIDEO_SERVICE_NAME, MAX_SERVICE_NAME_LEN); + } + // Generate the time CHK_STATUS(generateSignatureDateTime(pRequestInfo->currentTime, dateTimeStr)); @@ -498,8 +508,13 @@ STATUS generateCanonicalRequestString(PRequestInfo pRequestInfo, PCHAR pRequestS len = SHA256_DIGEST_LENGTH * 2; CHK(curLen + len <= requestLen, STATUS_BUFFER_TOO_SMALL); if (pRequestInfo->body == NULL) { - // Streaming treats this portion as if the body were empty - CHK_STATUS(hexEncodedSha256((PBYTE) EMPTY_STRING, 0, pCurPtr)); + if (STRNCMP(pRequestInfo->service, KINESIS_VIDEO_SERVICE_NAME, MAX_SERVICE_NAME_LEN) == 0) { + // Streaming treats this portion as if the body were empty + CHK_STATUS(hexEncodedSha256((PBYTE) EMPTY_STRING, 0, pCurPtr)); + } else { + len = (UINT32) (ARRAY_SIZE(PREDEFINED_UNSIGNED_PAYLOAD) - 1); + MEMCPY(pCurPtr, PREDEFINED_UNSIGNED_PAYLOAD, SIZEOF(CHAR) * len); + } } else { // standard signing CHK_STATUS(hexEncodedSha256((PBYTE) pRequestInfo->body, pRequestInfo->bodySize, pCurPtr)); @@ -678,14 +693,14 @@ STATUS generateCredentialScope(PRequestInfo pRequestInfo, PCHAR dateTimeStr, PCH CHK(pRequestInfo != NULL && dateTimeStr != NULL && pScopeLen != NULL, STATUS_NULL_ARG); // Calculate the max string length with a null terminator at the end - scopeLen = SIGNATURE_DATE_TIME_STRING_LEN + 1 + MAX_REGION_NAME_LEN + 1 + (UINT32) STRLEN(KINESIS_VIDEO_SERVICE_NAME) + 1 + + scopeLen = SIGNATURE_DATE_TIME_STRING_LEN + 1 + MAX_REGION_NAME_LEN + 1 + (UINT32) STRNLEN(pRequestInfo->service, MAX_SERVICE_NAME_LEN) + 1 + (UINT32) STRLEN(AWS_SIG_V4_SIGNATURE_END) + 1; // Early exit on buffer calculation CHK(pScope != NULL, retStatus); scopeLen = (UINT32) SNPRINTF(pScope, *pScopeLen, CREDENTIAL_SCOPE_TEMPLATE, SIGNATURE_DATE_STRING_LEN, dateTimeStr, pRequestInfo->region, - KINESIS_VIDEO_SERVICE_NAME, AWS_SIG_V4_SIGNATURE_END); + pRequestInfo->service, AWS_SIG_V4_SIGNATURE_END); CHK(scopeLen > 0 && scopeLen <= *pScopeLen, STATUS_BUFFER_TOO_SMALL); CleanUp: @@ -707,7 +722,7 @@ STATUS generateEncodedCredentials(PRequestInfo pRequestInfo, PCHAR dateTimeStr, CHK(pRequestInfo != NULL && dateTimeStr != NULL && pCredsLen != NULL, STATUS_NULL_ARG); // Calculate the max string length with '/' and a null terminator at the end - credsLen = MAX_ACCESS_KEY_LEN + 1 + SIGNATURE_DATE_TIME_STRING_LEN + 1 + MAX_REGION_NAME_LEN + 1 + (UINT32) STRLEN(KINESIS_VIDEO_SERVICE_NAME) + + credsLen = MAX_ACCESS_KEY_LEN + 1 + SIGNATURE_DATE_TIME_STRING_LEN + 1 + MAX_REGION_NAME_LEN + 1 + (UINT32) STRNLEN(pRequestInfo->service, MAX_SERVICE_NAME_LEN) + 1 + (UINT32) STRLEN(AWS_SIG_V4_SIGNATURE_END) + 1; // Early exit on buffer calculation @@ -715,7 +730,7 @@ STATUS generateEncodedCredentials(PRequestInfo pRequestInfo, PCHAR dateTimeStr, credsLen = (UINT32) SNPRINTF(pCreds, *pCredsLen, URL_ENCODED_CREDENTIAL_TEMPLATE, pRequestInfo->pAwsCredentials->accessKeyIdLen, pRequestInfo->pAwsCredentials->accessKeyId, SIGNATURE_DATE_STRING_LEN, dateTimeStr, pRequestInfo->region, - KINESIS_VIDEO_SERVICE_NAME, AWS_SIG_V4_SIGNATURE_END); + pRequestInfo->service, AWS_SIG_V4_SIGNATURE_END); CHK(credsLen > 0 && credsLen <= *pCredsLen, STATUS_BUFFER_TOO_SMALL); CleanUp: diff --git a/src/source/Common/AwsV4Signer.h b/src/source/Common/AwsV4Signer.h index 71208e2da..ea9a7f622 100644 --- a/src/source/Common/AwsV4Signer.h +++ b/src/source/Common/AwsV4Signer.h @@ -82,6 +82,8 @@ extern "C" { #define KVS_MAX_HMAC_SIZE 64 +#define PREDEFINED_UNSIGNED_PAYLOAD "UNSIGNED-PAYLOAD" + //////////////////////////////////////////////////// // Function definitions //////////////////////////////////////////////////// From 4f1e7980d9fbc95bd9c91044c596deef16e0c426 Mon Sep 17 00:00:00 2001 From: Niyati Maheshwari Date: Wed, 29 Nov 2023 09:05:12 -0800 Subject: [PATCH 03/12] Introduce M1 build in the CI (#419) * m1 build * cmake update * run tests in m1 --- .github/workflows/ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d2fd5547..eabeb418d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,6 +85,35 @@ jobs: cd build ./tst/producer_test + mac-os-m1-build-clang: + runs-on: macos-13-xlarge + env: + AWS_KVS_LOG_LEVEL: 2 + permissions: + id-token: write + contents: read + steps: + - name: Clone repository + uses: actions/checkout@v3 + - name: Build repository + run: | + brew install pkgconfig + brew unlink openssl # it seems the libcurl is trying to access this openssl despite explicitly setting it to our build + mkdir build && cd build + sh -c 'cmake .. -DBUILD_TEST=TRUE -DCOMPILER_WARNINGS=TRUE -DCMAKE_C_COMPILER=$(brew --prefix llvm@15)/bin/clang -DCMAKE_CXX_COMPILER=$(brew --prefix llvm@15)/bin/clang++;cmake .. -DBUILD_TEST=TRUE -DCOMPILER_WARNINGS=TRUE -DCMAKE_C_COMPILER=$(brew --prefix llvm@15)/bin/clang -DCMAKE_CXX_COMPILER=$(brew --prefix llvm@15)/bin/clang++' + make + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1-node16 + with: + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION_NAME }} + aws-region: ${{ secrets.AWS_REGION }} + role-duration-seconds: 10800 + - name: Run tests + run: | + cd build + ./tst/producer_test + mac-os-build-gcc-local-openssl: runs-on: macos-11 permissions: From 52f562f9d4aaa05018f1f265df30fdc23f30d537 Mon Sep 17 00:00:00 2001 From: Dave Johansen Date: Thu, 10 Aug 2023 13:23:02 -0600 Subject: [PATCH 04/12] Add setting of fragment meta to the sample --- samples/KvsVideoOnlyRealtimeStreamingSample.c | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/samples/KvsVideoOnlyRealtimeStreamingSample.c b/samples/KvsVideoOnlyRealtimeStreamingSample.c index a5e3d2efc..fe032b98e 100644 --- a/samples/KvsVideoOnlyRealtimeStreamingSample.c +++ b/samples/KvsVideoOnlyRealtimeStreamingSample.c @@ -68,10 +68,12 @@ INT32 main(INT32 argc, CHAR* argv[]) CHAR videoCodec[VIDEO_CODEC_NAME_MAX_LENGTH]; STRNCPY(videoCodec, VIDEO_CODEC_NAME_H264, STRLEN(VIDEO_CODEC_NAME_H264)); // h264 video by default VIDEO_CODEC_ID videoCodecID = VIDEO_CODEC_ID_H264; + int n, numMetadata = 0; + char key[200], value[200]; if (argc < 2) { DLOGE("Usage: AWS_ACCESS_KEY_ID=SAMPLEKEY AWS_SECRET_ACCESS_KEY=SAMPLESECRET %s " - "\n", + " [num_metadata]\n", argv[0]); CHK(FALSE, STATUS_INVALID_ARG); } @@ -82,7 +84,7 @@ INT32 main(INT32 argc, CHAR* argv[]) } MEMSET(frameFilePath, 0x00, MAX_PATH_LEN + 1); - if (argc < 5) { + if (argc < 5 || STRLEN(argv[4]) == 0) { STRCPY(frameFilePath, (PCHAR) "../samples/"); } else { STRNCPY(frameFilePath, argv[4], MAX_PATH_LEN); @@ -95,19 +97,23 @@ INT32 main(INT32 argc, CHAR* argv[]) region = (PCHAR) DEFAULT_AWS_REGION; } - if (argc >= 3) { + if (argc >= 3 && STRLEN(argv[2]) > 0) { if (!STRCMP(argv[2], VIDEO_CODEC_NAME_H265)) { STRNCPY(videoCodec, VIDEO_CODEC_NAME_H265, STRLEN(VIDEO_CODEC_NAME_H265)); videoCodecID = VIDEO_CODEC_ID_H265; } } - if (argc >= 4) { + if (argc >= 4 && STRLEN(argv[3]) > 0) { // Get the duration and convert to an integer CHK_STATUS(STRTOUI64(argv[3], NULL, 10, &streamingDuration)); streamingDuration *= HUNDREDS_OF_NANOS_IN_A_SECOND; } + if (argc >= 6 && STRLEN(argv[5]) > 0) { + numMetadata = STRTOUL(argv[5], NULL, 10); + } + streamStopTime = GETTIME() + streamingDuration; // default storage size is 128MB. Use setDeviceInfoStorageSize after create to change storage size. @@ -154,6 +160,18 @@ INT32 main(INT32 argc, CHAR* argv[]) CHK_STATUS(readFrameData(&frame, frameFilePath, videoCodec)); + if (frame.flags == FRAME_FLAG_KEY_FRAME) { + for (n=0; n Date: Tue, 5 Dec 2023 12:55:24 -0800 Subject: [PATCH 05/12] Formatting + style --- samples/KvsVideoOnlyRealtimeStreamingSample.c | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/samples/KvsVideoOnlyRealtimeStreamingSample.c b/samples/KvsVideoOnlyRealtimeStreamingSample.c index fe032b98e..b0fb9a698 100644 --- a/samples/KvsVideoOnlyRealtimeStreamingSample.c +++ b/samples/KvsVideoOnlyRealtimeStreamingSample.c @@ -11,6 +11,8 @@ #define VIDEO_CODEC_NAME_H264 "h264" #define VIDEO_CODEC_NAME_H265 "h265" #define VIDEO_CODEC_NAME_MAX_LENGTH 5 +#define METADATA_MAX_KEY_LENGTH 128 +#define METADATA_MAX_VALUE_LENGTH 256 #define NUMBER_OF_FRAME_FILES 403 @@ -57,10 +59,10 @@ INT32 main(INT32 argc, CHAR* argv[]) STREAM_HANDLE streamHandle = INVALID_STREAM_HANDLE_VALUE; STATUS retStatus = STATUS_SUCCESS; PCHAR accessKey = NULL, secretKey = NULL, sessionToken = NULL, streamName = NULL, region = NULL, cacertPath = NULL; - CHAR frameFilePath[MAX_PATH_LEN + 1]; + CHAR frameFilePath[MAX_PATH_LEN + 1], metadataKey[METADATA_MAX_KEY_LENGTH + 1], metadataValue[METADATA_MAX_VALUE_LENGTH + 1]; Frame frame; BYTE frameBuffer[200000]; // Assuming this is enough - UINT32 frameSize = SIZEOF(frameBuffer), frameIndex = 0, fileIndex = 0; + UINT32 frameSize = SIZEOF(frameBuffer), frameIndex = 0, fileIndex = 0, n = 0, numMetadata = 10; UINT64 streamStopTime, streamingDuration = DEFAULT_STREAM_DURATION; DOUBLE startUpLatency; BOOL firstFrame = TRUE; @@ -68,8 +70,6 @@ INT32 main(INT32 argc, CHAR* argv[]) CHAR videoCodec[VIDEO_CODEC_NAME_MAX_LENGTH]; STRNCPY(videoCodec, VIDEO_CODEC_NAME_H264, STRLEN(VIDEO_CODEC_NAME_H264)); // h264 video by default VIDEO_CODEC_ID videoCodecID = VIDEO_CODEC_ID_H264; - int n, numMetadata = 0; - char key[200], value[200]; if (argc < 2) { DLOGE("Usage: AWS_ACCESS_KEY_ID=SAMPLEKEY AWS_SECRET_ACCESS_KEY=SAMPLESECRET %s " @@ -83,13 +83,6 @@ INT32 main(INT32 argc, CHAR* argv[]) CHK(FALSE, STATUS_INVALID_ARG); } - MEMSET(frameFilePath, 0x00, MAX_PATH_LEN + 1); - if (argc < 5 || STRLEN(argv[4]) == 0) { - STRCPY(frameFilePath, (PCHAR) "../samples/"); - } else { - STRNCPY(frameFilePath, argv[4], MAX_PATH_LEN); - } - cacertPath = getenv(CACERT_PATH_ENV_VAR); sessionToken = getenv(SESSION_TOKEN_ENV_VAR); streamName = argv[1]; @@ -110,6 +103,13 @@ INT32 main(INT32 argc, CHAR* argv[]) streamingDuration *= HUNDREDS_OF_NANOS_IN_A_SECOND; } + MEMSET(frameFilePath, 0x00, MAX_PATH_LEN + 1); + if (argc < 5 || STRLEN(argv[4]) == 0) { + STRCPY(frameFilePath, (PCHAR) "../samples/"); + } else { + STRNCPY(frameFilePath, argv[4], MAX_PATH_LEN); + } + if (argc >= 6 && STRLEN(argv[5]) > 0) { numMetadata = STRTOUL(argv[5], NULL, 10); } @@ -160,15 +160,14 @@ INT32 main(INT32 argc, CHAR* argv[]) CHK_STATUS(readFrameData(&frame, frameFilePath, videoCodec)); + // Add the fragment metadata key-value pairs + // For limits, refer to https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/limits.html#limits-streaming-metadata if (frame.flags == FRAME_FLAG_KEY_FRAME) { - for (n=0; n Date: Tue, 5 Dec 2023 13:35:37 -0800 Subject: [PATCH 06/12] More style --- samples/KvsVideoOnlyRealtimeStreamingSample.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/samples/KvsVideoOnlyRealtimeStreamingSample.c b/samples/KvsVideoOnlyRealtimeStreamingSample.c index b0fb9a698..6d0a9f0b4 100644 --- a/samples/KvsVideoOnlyRealtimeStreamingSample.c +++ b/samples/KvsVideoOnlyRealtimeStreamingSample.c @@ -13,6 +13,7 @@ #define VIDEO_CODEC_NAME_MAX_LENGTH 5 #define METADATA_MAX_KEY_LENGTH 128 #define METADATA_MAX_VALUE_LENGTH 256 +#define MAX_METADATA_PER_FRAGMENT 10 #define NUMBER_OF_FRAME_FILES 403 @@ -72,8 +73,8 @@ INT32 main(INT32 argc, CHAR* argv[]) VIDEO_CODEC_ID videoCodecID = VIDEO_CODEC_ID_H264; if (argc < 2) { - DLOGE("Usage: AWS_ACCESS_KEY_ID=SAMPLEKEY AWS_SECRET_ACCESS_KEY=SAMPLESECRET %s " - " [num_metadata]\n", + DLOGE("Usage: AWS_ACCESS_KEY_ID=SAMPLEKEY AWS_SECRET_ACCESS_KEY=SAMPLESECRET %s " + " [num_metadata = 10]\n", argv[0]); CHK(FALSE, STATUS_INVALID_ARG); } @@ -90,28 +91,30 @@ INT32 main(INT32 argc, CHAR* argv[]) region = (PCHAR) DEFAULT_AWS_REGION; } - if (argc >= 3 && STRLEN(argv[2]) > 0) { + if (argc >= 3 && !IS_EMPTY_STRING(argv[2])) { if (!STRCMP(argv[2], VIDEO_CODEC_NAME_H265)) { STRNCPY(videoCodec, VIDEO_CODEC_NAME_H265, STRLEN(VIDEO_CODEC_NAME_H265)); videoCodecID = VIDEO_CODEC_ID_H265; } } - if (argc >= 4 && STRLEN(argv[3]) > 0) { + if (argc >= 4 && !IS_EMPTY_STRING(argv[3])) { // Get the duration and convert to an integer CHK_STATUS(STRTOUI64(argv[3], NULL, 10, &streamingDuration)); streamingDuration *= HUNDREDS_OF_NANOS_IN_A_SECOND; } MEMSET(frameFilePath, 0x00, MAX_PATH_LEN + 1); - if (argc < 5 || STRLEN(argv[4]) == 0) { - STRCPY(frameFilePath, (PCHAR) "../samples/"); - } else { + if (argc >= 5 && !IS_EMPTY_STRING(argv[4])) { STRNCPY(frameFilePath, argv[4], MAX_PATH_LEN); + } else { + STRCPY(frameFilePath, (PCHAR) "../samples/"); } - if (argc >= 6 && STRLEN(argv[5]) > 0) { + if (argc >= 6 && !IS_EMPTY_STRING(argv[5])) { numMetadata = STRTOUL(argv[5], NULL, 10); + DLOGD("numMetadata: %d\n", numMetadata); + CHK(numMetadata <= MAX_METADATA_PER_FRAGMENT, STATUS_INVALID_ARG); } streamStopTime = GETTIME() + streamingDuration; From 59636246837a8641b53972d956f603ec438a55c1 Mon Sep 17 00:00:00 2001 From: Jeremy Gunawan Date: Tue, 5 Dec 2023 13:37:08 -0800 Subject: [PATCH 07/12] Small optimization --- samples/KvsVideoOnlyRealtimeStreamingSample.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/KvsVideoOnlyRealtimeStreamingSample.c b/samples/KvsVideoOnlyRealtimeStreamingSample.c index 6d0a9f0b4..a7a02d335 100644 --- a/samples/KvsVideoOnlyRealtimeStreamingSample.c +++ b/samples/KvsVideoOnlyRealtimeStreamingSample.c @@ -113,7 +113,7 @@ INT32 main(INT32 argc, CHAR* argv[]) if (argc >= 6 && !IS_EMPTY_STRING(argv[5])) { numMetadata = STRTOUL(argv[5], NULL, 10); - DLOGD("numMetadata: %d\n", numMetadata); + DLOGE("numMetadata: %d\n", numMetadata); CHK(numMetadata <= MAX_METADATA_PER_FRAGMENT, STATUS_INVALID_ARG); } @@ -165,7 +165,7 @@ INT32 main(INT32 argc, CHAR* argv[]) // Add the fragment metadata key-value pairs // For limits, refer to https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/limits.html#limits-streaming-metadata - if (frame.flags == FRAME_FLAG_KEY_FRAME) { + if (numMetadata > 0 && frame.flags == FRAME_FLAG_KEY_FRAME) { DLOGD("Adding metadata! frameIndex: %d", frame.index); for (n = 1; n <= numMetadata; n++) { SNPRINTF(metadataKey, METADATA_MAX_KEY_LENGTH, "TEST_KEY_%d", n); From 27d593b948def61d1f57270dea5d6971c05c0b31 Mon Sep 17 00:00:00 2001 From: Jeremy Gunawan Date: Tue, 5 Dec 2023 15:03:27 -0800 Subject: [PATCH 08/12] Update readme --- README.md | 11 +++++++++++ samples/KvsVideoOnlyRealtimeStreamingSample.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e49af0f3e..0d658c4ca 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,17 @@ For audio only, run `./kvsAudioOnlyStreamingSample +``` + +`num-metadata` -- the number of sample fragment metadata key-value pairs that are added to each fragment. Min: 0, Max: 10. Default: 10. + ### Setting log levels diff --git a/samples/KvsVideoOnlyRealtimeStreamingSample.c b/samples/KvsVideoOnlyRealtimeStreamingSample.c index a7a02d335..2c8fe17ba 100644 --- a/samples/KvsVideoOnlyRealtimeStreamingSample.c +++ b/samples/KvsVideoOnlyRealtimeStreamingSample.c @@ -113,7 +113,7 @@ INT32 main(INT32 argc, CHAR* argv[]) if (argc >= 6 && !IS_EMPTY_STRING(argv[5])) { numMetadata = STRTOUL(argv[5], NULL, 10); - DLOGE("numMetadata: %d\n", numMetadata); + DLOGD("numMetadata: %d\n", numMetadata); CHK(numMetadata <= MAX_METADATA_PER_FRAGMENT, STATUS_INVALID_ARG); } From fd9e19f888a7347619964e975e154da0532f1f88 Mon Sep 17 00:00:00 2001 From: James Delaplane Date: Tue, 5 Dec 2023 15:13:23 -0800 Subject: [PATCH 09/12] Clang format --- src/source/Common/AwsV4Signer.c | 47 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/source/Common/AwsV4Signer.c b/src/source/Common/AwsV4Signer.c index d41780a3a..1e4e44b76 100644 --- a/src/source/Common/AwsV4Signer.c +++ b/src/source/Common/AwsV4Signer.c @@ -73,7 +73,8 @@ STATUS generateAwsSigV4Signature(PRequestInfo pRequestInfo, PCHAR dateTimeStr, B hmacSize = SIZEOF(hmac); CHK_STATUS(generateRequestHmac((PBYTE) pScratchBuf, curSize, (PBYTE) dateTimeStr, SIGNATURE_DATE_STRING_LEN * SIZEOF(CHAR), hmac, &hmacSize)); CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) pRequestInfo->region, (UINT32) STRLEN(pRequestInfo->region), hmac, &hmacSize)); - CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) pRequestInfo->service, (UINT32) STRNLEN(pRequestInfo->service, MAX_SERVICE_NAME_LEN), hmac, &hmacSize)); + CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) pRequestInfo->service, (UINT32) STRNLEN(pRequestInfo->service, MAX_SERVICE_NAME_LEN), hmac, + &hmacSize)); CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) AWS_SIG_V4_SIGNATURE_END, (UINT32) STRLEN(AWS_SIG_V4_SIGNATURE_END), hmac, &hmacSize)); CHK_STATUS(generateRequestHmac(hmac, hmacSize, (PBYTE) pSignedStr, signedStrLen * SIZEOF(CHAR), hmac, &hmacSize)); @@ -117,7 +118,8 @@ STATUS signAwsRequestInfo(PRequestInfo pRequestInfo) CHK(pRequestInfo != NULL && pRequestInfo->pAwsCredentials != NULL, STATUS_NULL_ARG); - // signAwsRequestInfo is a public api function, if service is not specified default to "kinesisvideo" so no breaking changes are introduced to the api + // signAwsRequestInfo is a public api function, if service is not specified default to "kinesisvideo" so no breaking changes are introduced to the + // api if (pRequestInfo->service[0] == L'\0') { STRNCPY(pRequestInfo->service, KINESIS_VIDEO_SERVICE_NAME, MAX_SERVICE_NAME_LEN); } @@ -127,7 +129,7 @@ STATUS signAwsRequestInfo(PRequestInfo pRequestInfo) // Get the host header CHK_STATUS(getRequestHost(pRequestInfo->url, &pHostStart, &pHostEnd)); - len = (UINT32) (pHostEnd - pHostStart); + len = (UINT32)(pHostEnd - pHostStart); CHK_STATUS(setRequestHeader(pRequestInfo, AWS_SIG_V4_HEADER_HOST, 0, pHostStart, len)); CHK_STATUS(setRequestHeader(pRequestInfo, AWS_SIG_V4_HEADER_AMZ_DATE, 0, dateTimeStr, 0)); @@ -172,7 +174,8 @@ STATUS signAwsRequestInfoQueryParam(PRequestInfo pRequestInfo) CHK(pRequestInfo != NULL && pRequestInfo->pAwsCredentials != NULL, STATUS_NULL_ARG); - // signAwsRequestInfoQueryParam is a public api function, if service is not specified default to "kinesisvideo" so no breaking changes are introduced to the api + // signAwsRequestInfoQueryParam is a public api function, if service is not specified default to "kinesisvideo" so no breaking changes are + // introduced to the api if (pRequestInfo->service[0] == L'\0') { STRNCPY(pRequestInfo->service, KINESIS_VIDEO_SERVICE_NAME, MAX_SERVICE_NAME_LEN); } @@ -182,7 +185,7 @@ STATUS signAwsRequestInfoQueryParam(PRequestInfo pRequestInfo) // Need to add host header CHK_STATUS(getRequestHost(pRequestInfo->url, &pHostStart, &pHostEnd)); - len = (UINT32) (pHostEnd - pHostStart); + len = (UINT32)(pHostEnd - pHostStart); CHK_STATUS(setRequestHeader(pRequestInfo, AWS_SIG_V4_HEADER_HOST, 0, pHostStart, len)); // Encode the credentials scope @@ -202,7 +205,7 @@ STATUS signAwsRequestInfoQueryParam(PRequestInfo pRequestInfo) // Calculate the expiration in seconds expirationInSeconds = MIN(MAX_AWS_SIGV4_CREDENTIALS_EXPIRATION_IN_SECONDS, - (UINT32) ((pRequestInfo->pAwsCredentials->expiration - pRequestInfo->currentTime) / HUNDREDS_OF_NANOS_IN_A_SECOND)); + (UINT32)((pRequestInfo->pAwsCredentials->expiration - pRequestInfo->currentTime) / HUNDREDS_OF_NANOS_IN_A_SECOND)); expirationInSeconds = MAX(MIN_AWS_SIGV4_CREDENTIALS_EXPIRATION_IN_SECONDS, expirationInSeconds); // Add the params @@ -288,7 +291,7 @@ STATUS getCanonicalQueryParams(PCHAR pUrl, UINT32 urlLen, BOOL uriEncode, PCHAR* CHK_STATUS(singleListCreate(&pSingleList)); while (iterate) { - pQueryParamEnd = STRNCHR(pQueryParamStart, (UINT32) (pEndPtr - pQueryParamStart), '&'); + pQueryParamEnd = STRNCHR(pQueryParamStart, (UINT32)(pEndPtr - pQueryParamStart), '&'); if (pQueryParamEnd == NULL) { // break the loop iterate = FALSE; @@ -297,12 +300,12 @@ STATUS getCanonicalQueryParams(PCHAR pUrl, UINT32 urlLen, BOOL uriEncode, PCHAR* } // Process the resulting param name and value - CHK(NULL != (pParamValue = STRNCHR(pQueryParamStart, (UINT32) (pQueryParamEnd - pQueryParamStart), '=')), STATUS_INVALID_ARG); - nameLen = (UINT32) (pParamValue - pQueryParamStart); + CHK(NULL != (pParamValue = STRNCHR(pQueryParamStart, (UINT32)(pQueryParamEnd - pQueryParamStart), '=')), STATUS_INVALID_ARG); + nameLen = (UINT32)(pParamValue - pQueryParamStart); // Advance param start past '=' pParamValue++; - valueLen = (UINT32) (pQueryParamEnd - pParamValue); + valueLen = (UINT32)(pQueryParamEnd - pParamValue); // Max len is 3 times the size of the allocation to account for max bloat for encoding maxLen = MIN(MAX_URI_CHAR_LEN, nameLen + 1 + valueLen * 3 + 1); @@ -391,7 +394,7 @@ STATUS getCanonicalQueryParams(PCHAR pUrl, UINT32 urlLen, BOOL uriEncode, PCHAR* } *pCurPtr = '\0'; - queryLen = (UINT32) (pCurPtr - pQuery); + queryLen = (UINT32)(pCurPtr - pQuery); CleanUp: @@ -467,7 +470,7 @@ STATUS generateCanonicalRequestString(PRequestInfo pRequestInfo, PCHAR pRequestS // Get the canonical URI CHK_STATUS(getCanonicalUri(pRequestInfo->url, urlLen, &pUriStart, &pUriEnd, &defaultPath)); - len = defaultPath ? 1 : (UINT32) (pUriEnd - pUriStart); + len = defaultPath ? 1 : (UINT32)(pUriEnd - pUriStart); CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL); MEMCPY(pCurPtr, pUriStart, len * SIZEOF(CHAR)); @@ -482,7 +485,7 @@ STATUS generateCanonicalRequestString(PRequestInfo pRequestInfo, PCHAR pRequestS // The start of the query params is either end of the URI or ? so we skip one in that case pQueryStart = (pUriEnd == pQueryEnd) ? pUriEnd : pUriEnd + 1; - len = (UINT32) (pQueryEnd - pQueryStart); + len = (UINT32)(pQueryEnd - pQueryStart); CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL); MEMCPY(pCurPtr, pQueryStart, len * SIZEOF(CHAR)); pCurPtr += len; @@ -512,7 +515,7 @@ STATUS generateCanonicalRequestString(PRequestInfo pRequestInfo, PCHAR pRequestS // Streaming treats this portion as if the body were empty CHK_STATUS(hexEncodedSha256((PBYTE) EMPTY_STRING, 0, pCurPtr)); } else { - len = (UINT32) (ARRAY_SIZE(PREDEFINED_UNSIGNED_PAYLOAD) - 1); + len = (UINT32)(ARRAY_SIZE(PREDEFINED_UNSIGNED_PAYLOAD) - 1); MEMCPY(pCurPtr, PREDEFINED_UNSIGNED_PAYLOAD, SIZEOF(CHAR) * len); } } else { @@ -561,7 +564,7 @@ STATUS generateCanonicalHeaders(PRequestInfo pRequestInfo, PCHAR pCanonicalHeade // Process only if we have a canonical header name if (IS_CANONICAL_HEADER_NAME(pRequestHeader->pName)) { CHK_STATUS(TRIMSTRALL(pRequestHeader->pValue, pRequestHeader->valueLen, &pStart, &pEnd)); - valueLen = (UINT32) (pEnd - pStart); + valueLen = (UINT32)(pEnd - pStart); // Increase the overall length as we use the lower-case header, colon, trimmed lower-case value and new line overallLen += pRequestHeader->nameLen + 1 + valueLen + 1; @@ -673,7 +676,7 @@ STATUS generateSignatureDateTime(UINT64 currentTime, PCHAR pDateTimeStr) CHK(pDateTimeStr != NULL, STATUS_NULL_ARG); // Convert to time_t - timeT = (time_t) (currentTime / HUNDREDS_OF_NANOS_IN_A_SECOND); + timeT = (time_t)(currentTime / HUNDREDS_OF_NANOS_IN_A_SECOND); retSize = STRFTIME(pDateTimeStr, SIGNATURE_DATE_TIME_STRING_LEN, DATE_TIME_STRING_FORMAT, GMTIME(&timeT)); CHK(retSize > 0, STATUS_BUFFER_TOO_SMALL); pDateTimeStr[retSize] = '\0'; @@ -722,8 +725,8 @@ STATUS generateEncodedCredentials(PRequestInfo pRequestInfo, PCHAR dateTimeStr, CHK(pRequestInfo != NULL && dateTimeStr != NULL && pCredsLen != NULL, STATUS_NULL_ARG); // Calculate the max string length with '/' and a null terminator at the end - credsLen = MAX_ACCESS_KEY_LEN + 1 + SIGNATURE_DATE_TIME_STRING_LEN + 1 + MAX_REGION_NAME_LEN + 1 + (UINT32) STRNLEN(pRequestInfo->service, MAX_SERVICE_NAME_LEN) + - 1 + (UINT32) STRLEN(AWS_SIG_V4_SIGNATURE_END) + 1; + credsLen = MAX_ACCESS_KEY_LEN + 1 + SIGNATURE_DATE_TIME_STRING_LEN + 1 + MAX_REGION_NAME_LEN + 1 + + (UINT32) STRNLEN(pRequestInfo->service, MAX_SERVICE_NAME_LEN) + 1 + (UINT32) STRLEN(AWS_SIG_V4_SIGNATURE_END) + 1; // Early exit on buffer calculation CHK(pCreds != NULL, retStatus); @@ -831,7 +834,7 @@ STATUS getCanonicalUri(PCHAR pUrl, UINT32 len, PCHAR* ppStart, PCHAR* ppEnd, PBO } else if (*pCur == '/') { // This is the case of the path which we find pStart = pCur; - pEnd = STRNCHR(pCur, urlLen - (UINT32) (pCur - pUrl), '?'); + pEnd = STRNCHR(pCur, urlLen - (UINT32)(pCur - pUrl), '?'); iterate = FALSE; } @@ -875,7 +878,7 @@ STATUS uriEncodeString(PCHAR pSrc, UINT32 srcLen, PCHAR pDst, PUINT32 pDstLen) CHK(pSrc != NULL && pDstLen != NULL, STATUS_NULL_ARG); - while (((UINT32) (pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr++) != '\0')) { + while (((UINT32)(pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr++) != '\0')) { if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.') { encodedLen++; @@ -939,9 +942,9 @@ STATUS uriDecodeString(PCHAR pSrc, UINT32 srcLen, PCHAR pDst, PUINT32 pDstLen) CHK(pSrc != NULL && pDstLen != NULL, STATUS_NULL_ARG); - while (((UINT32) (pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr) != '\0')) { + while (((UINT32)(pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr) != '\0')) { if (ch == '%') { - CHK((UINT32) (pCurPtr - pSrc) + decLen <= strLen && *(pCurPtr + 1) != '\0' && *(pCurPtr + 2) != '\0', STATUS_INVALID_ARG); + CHK((UINT32)(pCurPtr - pSrc) + decLen <= strLen && *(pCurPtr + 1) != '\0' && *(pCurPtr + 2) != '\0', STATUS_INVALID_ARG); if (pDec != NULL) { size = remaining; CHK_STATUS(hexDecode(pCurPtr + 1, 2, (PBYTE) pDec, &size)); From eebe8a7b9d4caa955a9aee205237fea6e738a673 Mon Sep 17 00:00:00 2001 From: James Delaplane Date: Tue, 5 Dec 2023 15:42:22 -0800 Subject: [PATCH 10/12] Clang format, again --- src/source/Common/AwsV4Signer.c | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/source/Common/AwsV4Signer.c b/src/source/Common/AwsV4Signer.c index 1e4e44b76..4c58739bf 100644 --- a/src/source/Common/AwsV4Signer.c +++ b/src/source/Common/AwsV4Signer.c @@ -129,7 +129,7 @@ STATUS signAwsRequestInfo(PRequestInfo pRequestInfo) // Get the host header CHK_STATUS(getRequestHost(pRequestInfo->url, &pHostStart, &pHostEnd)); - len = (UINT32)(pHostEnd - pHostStart); + len = (UINT32) (pHostEnd - pHostStart); CHK_STATUS(setRequestHeader(pRequestInfo, AWS_SIG_V4_HEADER_HOST, 0, pHostStart, len)); CHK_STATUS(setRequestHeader(pRequestInfo, AWS_SIG_V4_HEADER_AMZ_DATE, 0, dateTimeStr, 0)); @@ -185,7 +185,7 @@ STATUS signAwsRequestInfoQueryParam(PRequestInfo pRequestInfo) // Need to add host header CHK_STATUS(getRequestHost(pRequestInfo->url, &pHostStart, &pHostEnd)); - len = (UINT32)(pHostEnd - pHostStart); + len = (UINT32) (pHostEnd - pHostStart); CHK_STATUS(setRequestHeader(pRequestInfo, AWS_SIG_V4_HEADER_HOST, 0, pHostStart, len)); // Encode the credentials scope @@ -205,7 +205,7 @@ STATUS signAwsRequestInfoQueryParam(PRequestInfo pRequestInfo) // Calculate the expiration in seconds expirationInSeconds = MIN(MAX_AWS_SIGV4_CREDENTIALS_EXPIRATION_IN_SECONDS, - (UINT32)((pRequestInfo->pAwsCredentials->expiration - pRequestInfo->currentTime) / HUNDREDS_OF_NANOS_IN_A_SECOND)); + (UINT32) ((pRequestInfo->pAwsCredentials->expiration - pRequestInfo->currentTime) / HUNDREDS_OF_NANOS_IN_A_SECOND)); expirationInSeconds = MAX(MIN_AWS_SIGV4_CREDENTIALS_EXPIRATION_IN_SECONDS, expirationInSeconds); // Add the params @@ -291,7 +291,7 @@ STATUS getCanonicalQueryParams(PCHAR pUrl, UINT32 urlLen, BOOL uriEncode, PCHAR* CHK_STATUS(singleListCreate(&pSingleList)); while (iterate) { - pQueryParamEnd = STRNCHR(pQueryParamStart, (UINT32)(pEndPtr - pQueryParamStart), '&'); + pQueryParamEnd = STRNCHR(pQueryParamStart, (UINT32) (pEndPtr - pQueryParamStart), '&'); if (pQueryParamEnd == NULL) { // break the loop iterate = FALSE; @@ -300,12 +300,12 @@ STATUS getCanonicalQueryParams(PCHAR pUrl, UINT32 urlLen, BOOL uriEncode, PCHAR* } // Process the resulting param name and value - CHK(NULL != (pParamValue = STRNCHR(pQueryParamStart, (UINT32)(pQueryParamEnd - pQueryParamStart), '=')), STATUS_INVALID_ARG); - nameLen = (UINT32)(pParamValue - pQueryParamStart); + CHK(NULL != (pParamValue = STRNCHR(pQueryParamStart, (UINT32) (pQueryParamEnd - pQueryParamStart), '=')), STATUS_INVALID_ARG); + nameLen = (UINT32) (pParamValue - pQueryParamStart); // Advance param start past '=' pParamValue++; - valueLen = (UINT32)(pQueryParamEnd - pParamValue); + valueLen = (UINT32) (pQueryParamEnd - pParamValue); // Max len is 3 times the size of the allocation to account for max bloat for encoding maxLen = MIN(MAX_URI_CHAR_LEN, nameLen + 1 + valueLen * 3 + 1); @@ -394,7 +394,7 @@ STATUS getCanonicalQueryParams(PCHAR pUrl, UINT32 urlLen, BOOL uriEncode, PCHAR* } *pCurPtr = '\0'; - queryLen = (UINT32)(pCurPtr - pQuery); + queryLen = (UINT32) (pCurPtr - pQuery); CleanUp: @@ -470,7 +470,7 @@ STATUS generateCanonicalRequestString(PRequestInfo pRequestInfo, PCHAR pRequestS // Get the canonical URI CHK_STATUS(getCanonicalUri(pRequestInfo->url, urlLen, &pUriStart, &pUriEnd, &defaultPath)); - len = defaultPath ? 1 : (UINT32)(pUriEnd - pUriStart); + len = defaultPath ? 1 : (UINT32) (pUriEnd - pUriStart); CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL); MEMCPY(pCurPtr, pUriStart, len * SIZEOF(CHAR)); @@ -485,7 +485,7 @@ STATUS generateCanonicalRequestString(PRequestInfo pRequestInfo, PCHAR pRequestS // The start of the query params is either end of the URI or ? so we skip one in that case pQueryStart = (pUriEnd == pQueryEnd) ? pUriEnd : pUriEnd + 1; - len = (UINT32)(pQueryEnd - pQueryStart); + len = (UINT32) (pQueryEnd - pQueryStart); CHK(curLen + len + 1 <= requestLen, STATUS_BUFFER_TOO_SMALL); MEMCPY(pCurPtr, pQueryStart, len * SIZEOF(CHAR)); pCurPtr += len; @@ -515,7 +515,7 @@ STATUS generateCanonicalRequestString(PRequestInfo pRequestInfo, PCHAR pRequestS // Streaming treats this portion as if the body were empty CHK_STATUS(hexEncodedSha256((PBYTE) EMPTY_STRING, 0, pCurPtr)); } else { - len = (UINT32)(ARRAY_SIZE(PREDEFINED_UNSIGNED_PAYLOAD) - 1); + len = (UINT32) (ARRAY_SIZE(PREDEFINED_UNSIGNED_PAYLOAD) - 1); MEMCPY(pCurPtr, PREDEFINED_UNSIGNED_PAYLOAD, SIZEOF(CHAR) * len); } } else { @@ -564,7 +564,7 @@ STATUS generateCanonicalHeaders(PRequestInfo pRequestInfo, PCHAR pCanonicalHeade // Process only if we have a canonical header name if (IS_CANONICAL_HEADER_NAME(pRequestHeader->pName)) { CHK_STATUS(TRIMSTRALL(pRequestHeader->pValue, pRequestHeader->valueLen, &pStart, &pEnd)); - valueLen = (UINT32)(pEnd - pStart); + valueLen = (UINT32) (pEnd - pStart); // Increase the overall length as we use the lower-case header, colon, trimmed lower-case value and new line overallLen += pRequestHeader->nameLen + 1 + valueLen + 1; @@ -676,7 +676,7 @@ STATUS generateSignatureDateTime(UINT64 currentTime, PCHAR pDateTimeStr) CHK(pDateTimeStr != NULL, STATUS_NULL_ARG); // Convert to time_t - timeT = (time_t)(currentTime / HUNDREDS_OF_NANOS_IN_A_SECOND); + timeT = (time_t) (currentTime / HUNDREDS_OF_NANOS_IN_A_SECOND); retSize = STRFTIME(pDateTimeStr, SIGNATURE_DATE_TIME_STRING_LEN, DATE_TIME_STRING_FORMAT, GMTIME(&timeT)); CHK(retSize > 0, STATUS_BUFFER_TOO_SMALL); pDateTimeStr[retSize] = '\0'; @@ -834,7 +834,7 @@ STATUS getCanonicalUri(PCHAR pUrl, UINT32 len, PCHAR* ppStart, PCHAR* ppEnd, PBO } else if (*pCur == '/') { // This is the case of the path which we find pStart = pCur; - pEnd = STRNCHR(pCur, urlLen - (UINT32)(pCur - pUrl), '?'); + pEnd = STRNCHR(pCur, urlLen - (UINT32) (pCur - pUrl), '?'); iterate = FALSE; } @@ -878,7 +878,7 @@ STATUS uriEncodeString(PCHAR pSrc, UINT32 srcLen, PCHAR pDst, PUINT32 pDstLen) CHK(pSrc != NULL && pDstLen != NULL, STATUS_NULL_ARG); - while (((UINT32)(pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr++) != '\0')) { + while (((UINT32) (pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr++) != '\0')) { if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.') { encodedLen++; @@ -942,9 +942,9 @@ STATUS uriDecodeString(PCHAR pSrc, UINT32 srcLen, PCHAR pDst, PUINT32 pDstLen) CHK(pSrc != NULL && pDstLen != NULL, STATUS_NULL_ARG); - while (((UINT32)(pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr) != '\0')) { + while (((UINT32) (pCurPtr - pSrc) < strLen) && ((ch = *pCurPtr) != '\0')) { if (ch == '%') { - CHK((UINT32)(pCurPtr - pSrc) + decLen <= strLen && *(pCurPtr + 1) != '\0' && *(pCurPtr + 2) != '\0', STATUS_INVALID_ARG); + CHK((UINT32) (pCurPtr - pSrc) + decLen <= strLen && *(pCurPtr + 1) != '\0' && *(pCurPtr + 2) != '\0', STATUS_INVALID_ARG); if (pDec != NULL) { size = remaining; CHK_STATUS(hexDecode(pCurPtr + 1, 2, (PBYTE) pDec, &size)); From 70a42f71a0a72f1468158d2c002e064def7549b8 Mon Sep 17 00:00:00 2001 From: Stefan Kieszkowski <85728496+stefankiesz@users.noreply.github.com> Date: Wed, 6 Dec 2023 10:12:38 -0800 Subject: [PATCH 11/12] Add gcc paths (#420) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eabeb418d..5ce565edb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,8 +29,8 @@ jobs: id-token: write contents: read env: - CC: gcc - CXX: g++ + CC: /usr/local/bin/gcc-13 + CXX: /usr/local/bin/g++-13 AWS_KVS_LOG_LEVEL: 2 steps: - name: Clone repository @@ -120,8 +120,8 @@ jobs: id-token: write contents: read env: - CC: gcc - CXX: g++ + CC: /usr/local/bin/gcc-13 + CXX: /usr/local/bin/g++-13 AWS_KVS_LOG_LEVEL: 2 LDFLAGS: -L/usr/local/opt/openssl@3/lib CPPFLAGS: -I/usr/local/opt/openssl@3/include From 94b9b0cf8f861b512b0ab07df03a3443b3887ac4 Mon Sep 17 00:00:00 2001 From: Stefan Kieszkowski <85728496+stefankiesz@users.noreply.github.com> Date: Wed, 6 Dec 2023 10:23:48 -0800 Subject: [PATCH 12/12] spotaws PR #226 (#423) * proper versioned shared libs * Fix version * Update to latest version * Exclude shared builds from windows --------- Co-authored-by: Tom spot Callaway Co-authored-by: Divya Sampath Kumar Co-authored-by: Hassan Sahibzada --- CMakeLists.txt | 36 +++++++++++++++++++++++++++++------- libcproducer.pc.cmake | 2 +- libkvsCommonCurl.pc.cmake | 2 +- libkvsCommonLws.pc.cmake | 2 +- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd6bc22cc..8310dd98f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,11 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") include(Utilities) project(KinesisVideoProducerC VERSION 1.5.1 LANGUAGES C) +set(KINESIS_VIDEO_PRODUCER_C_MAJOR_VERSION 1) +set(KINESIS_VIDEO_PRODUCER_C_MINOR_VERSION 5) +set(KINESIS_VIDEO_PRODUCER_C_PATCH_VERSION 1) +set(KINESIS_VIDEO_PRODUCER_C_VERSION ${KINESIS_VIDEO_PRODUCER_C_MAJOR_VERSION}.${KINESIS_VIDEO_PRODUCER_C_MINOR_VERSION}.${KINESIS_VIDEO_PRODUCER_C_PATCH_VERSION}) + include(GNUInstallDirs) @@ -29,6 +34,11 @@ option(UNDEFINED_BEHAVIOR_SANITIZER "Build with UndefinedBehaviorSanitizer." OFF option(ALIGNED_MEMORY_MODEL "Aligned memory model ONLY." OFF) option(SET_SSL_CALLBACKS "Set SSL thread and lock callbacks." OFF) +set(TYPE_OF_LIB SHARED) +if (BUILD_STATIC) + set(TYPE_OF_LIB STATIC) +endif() + set(CMAKE_MACOSX_RPATH TRUE) get_filename_component(ROOT "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) @@ -262,8 +272,15 @@ if(BUILD_COMMON_LWS) "${CMAKE_CURRENT_SOURCE_DIR}/libkvsCommonLws.pc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/libkvsCommonLws.pc" @ONLY) - add_library(kvsCommonLws STATIC ${KVS_COMMON_SOURCE_FILES_BASE} ${KVS_COMMON_SOURCE_FILES_LWS}) + if (WIN32) + add_library(kvsCommonLws STATIC ${KVS_COMMON_SOURCE_FILES_BASE} ${KVS_COMMON_SOURCE_FILES_LWS}) + else() + add_library(kvsCommonLws ${TYPE_OF_LIB} ${KVS_COMMON_SOURCE_FILES_BASE} ${KVS_COMMON_SOURCE_FILES_LWS}) + endif() target_compile_definitions(kvsCommonLws PRIVATE KVS_BUILD_WITH_LWS ${CPRODUCER_COMMON_TLS_OPTION}) + if(NOT BUILD_STATIC) + set_target_properties(kvsCommonLws PROPERTIES VERSION ${KINESIS_VIDEO_PRODUCER_C_VERSION} SOVERSION ${KINESIS_VIDEO_PRODUCER_C_MAJOR_VERSION}) + endif() target_link_libraries(kvsCommonLws ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY} @@ -295,8 +312,15 @@ if(BUILD_COMMON_CURL) endif() endif() - add_library(kvsCommonCurl STATIC ${KVS_COMMON_SOURCE_FILES_BASE} ${KVS_COMMON_SOURCE_FILES_CURL}) + if (WIN32) + add_library(kvsCommonCurl STATIC ${KVS_COMMON_SOURCE_FILES_BASE} ${KVS_COMMON_SOURCE_FILES_CURL}) + else() + add_library(kvsCommonCurl ${TYPE_OF_LIB} ${KVS_COMMON_SOURCE_FILES_BASE} ${KVS_COMMON_SOURCE_FILES_CURL}) + endif() target_compile_definitions(kvsCommonCurl PRIVATE KVS_BUILD_WITH_CURL ${CPRODUCER_COMMON_TLS_OPTION}) + if(NOT BUILD_STATIC) + set_target_properties(kvsCommonCurl PROPERTIES VERSION ${KINESIS_VIDEO_PRODUCER_C_VERSION} SOVERSION ${KINESIS_VIDEO_PRODUCER_C_MAJOR_VERSION}) + endif() target_link_libraries(kvsCommonCurl kvspicUtils ${CURL_LIBRARIES} @@ -315,16 +339,14 @@ if(BUILD_COMMON_CURL) "${CMAKE_CURRENT_SOURCE_DIR}/libcproducer.pc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/libcproducer.pc" @ONLY) - set(TYPE_OF_LIB SHARED) - if (BUILD_STATIC) - set(TYPE_OF_LIB STATIC) - endif() - if (WIN32) add_library(cproducer STATIC ${PRODUCER_C_SOURCE_FILES}) else() add_library(cproducer ${TYPE_OF_LIB} ${PRODUCER_C_SOURCE_FILES}) endif() + if(NOT BUILD_STATIC) + set_target_properties(cproducer PROPERTIES VERSION ${KINESIS_VIDEO_PRODUCER_C_VERSION} SOVERSION ${KINESIS_VIDEO_PRODUCER_C_MAJOR_VERSION}) + endif() target_link_libraries(cproducer PUBLIC kvsCommonCurl kvspic) install( diff --git a/libcproducer.pc.cmake b/libcproducer.pc.cmake index 6391fd051..f4bfe45bb 100644 --- a/libcproducer.pc.cmake +++ b/libcproducer.pc.cmake @@ -5,6 +5,6 @@ libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ Name: KVS-libcproducer Description: KVS C Producer library -Version: 0.0.0 +Version: @KINESIS_VIDEO_PRODUCER_C_VERSION@ Cflags: -I${includedir} Libs: -L${libdir} -lcproducer diff --git a/libkvsCommonCurl.pc.cmake b/libkvsCommonCurl.pc.cmake index 86325a40f..b2a3e47bd 100644 --- a/libkvsCommonCurl.pc.cmake +++ b/libkvsCommonCurl.pc.cmake @@ -5,6 +5,6 @@ libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ Name: KVS-libkvsCommonCurl Description: KVS C Producer common curl library -Version: 0.0.0 +Version: @KINESIS_VIDEO_PRODUCER_C_VERSION@ Cflags: -I${includedir} Libs: -L${libdir} -lkvsCommonCurl diff --git a/libkvsCommonLws.pc.cmake b/libkvsCommonLws.pc.cmake index 975ae9c9e..04cb0f153 100644 --- a/libkvsCommonLws.pc.cmake +++ b/libkvsCommonLws.pc.cmake @@ -5,6 +5,6 @@ libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ Name: KVS-libkvsCommonLws Description: KVS C Producer common libwebsockets library -Version: 0.0.0 +Version: @KINESIS_VIDEO_PRODUCER_C_VERSION@ Cflags: -I${includedir} Libs: -L${libdir} -lkvsCommonLws