STATUS createValidateChannelInfo()

in src/source/Signaling/ChannelInfo.c [4:190]


STATUS createValidateChannelInfo(PChannelInfo pOrigChannelInfo, PChannelInfo* ppChannelInfo)
{
    ENTERS();
    STATUS retStatus = STATUS_SUCCESS;

    UINT32 allocSize, nameLen = 0, arnLen = 0, regionLen = 0, cplLen = 0, certLen = 0, postfixLen = 0, agentLen = 0, userAgentLen = 0, kmsLen = 0,
                      tagsSize;
    PCHAR pCurPtr, pRegionPtr;
    PChannelInfo pChannelInfo = NULL;

    CHK(pOrigChannelInfo != NULL && ppChannelInfo != NULL, STATUS_NULL_ARG);

    CHK((pOrigChannelInfo->pChannelName != NULL || pOrigChannelInfo->pChannelArn != NULL) && ppChannelInfo != NULL, STATUS_NULL_ARG);

    // Get and validate the lengths for all strings and store lengths excluding null terminator
    if (pOrigChannelInfo->pChannelName != NULL) {
        CHK((nameLen = (UINT32) STRNLEN(pOrigChannelInfo->pChannelName, MAX_CHANNEL_NAME_LEN + 1)) <= MAX_CHANNEL_NAME_LEN,
            STATUS_SIGNALING_INVALID_CHANNEL_NAME_LENGTH);
    }

    if (pOrigChannelInfo->pChannelArn != NULL) {
        CHK((arnLen = (UINT32) STRNLEN(pOrigChannelInfo->pChannelArn, MAX_ARN_LEN + 1)) <= MAX_ARN_LEN, STATUS_SIGNALING_INVALID_CHANNEL_ARN_LENGTH);
    }

    // Fix-up the region
    if (pOrigChannelInfo->pRegion != NULL) {
        CHK((regionLen = (UINT32) STRNLEN(pOrigChannelInfo->pRegion, MAX_REGION_NAME_LEN + 1)) <= MAX_REGION_NAME_LEN,
            STATUS_SIGNALING_INVALID_REGION_LENGTH);
        pRegionPtr = pOrigChannelInfo->pRegion;
    } else {
        regionLen = ARRAY_SIZE(DEFAULT_AWS_REGION) - 1;
        pRegionPtr = DEFAULT_AWS_REGION;
    }

    if (pOrigChannelInfo->pControlPlaneUrl != NULL) {
        CHK((cplLen = (UINT32) STRNLEN(pOrigChannelInfo->pControlPlaneUrl, MAX_URI_CHAR_LEN + 1)) <= MAX_URI_CHAR_LEN,
            STATUS_SIGNALING_INVALID_CPL_LENGTH);
    } else {
        cplLen = MAX_CONTROL_PLANE_URI_CHAR_LEN;
    }

    if (pOrigChannelInfo->pCertPath != NULL) {
        CHK((certLen = (UINT32) STRNLEN(pOrigChannelInfo->pCertPath, MAX_PATH_LEN + 1)) <= MAX_PATH_LEN,
            STATUS_SIGNALING_INVALID_CERTIFICATE_PATH_LENGTH);
    }

    userAgentLen = MAX_USER_AGENT_LEN;

    if (pOrigChannelInfo->pUserAgentPostfix != NULL) {
        CHK((postfixLen = (UINT32) STRNLEN(pOrigChannelInfo->pUserAgentPostfix, MAX_CUSTOM_USER_AGENT_NAME_POSTFIX_LEN + 1)) <=
                MAX_CUSTOM_USER_AGENT_NAME_POSTFIX_LEN,
            STATUS_SIGNALING_INVALID_AGENT_POSTFIX_LENGTH);
    }

    if (pOrigChannelInfo->pCustomUserAgent != NULL) {
        CHK((agentLen = (UINT32) STRNLEN(pOrigChannelInfo->pCustomUserAgent, MAX_CUSTOM_USER_AGENT_LEN + 1)) <= MAX_CUSTOM_USER_AGENT_LEN,
            STATUS_SIGNALING_INVALID_AGENT_LENGTH);
    }

    if (pOrigChannelInfo->pKmsKeyId != NULL) {
        CHK((kmsLen = (UINT32) STRNLEN(pOrigChannelInfo->pKmsKeyId, MAX_ARN_LEN + 1)) <= MAX_ARN_LEN, STATUS_SIGNALING_INVALID_KMS_KEY_LENGTH);
    }

    if (pOrigChannelInfo->messageTtl == 0) {
        pOrigChannelInfo->messageTtl = SIGNALING_DEFAULT_MESSAGE_TTL_VALUE;
    } else {
        CHK(pOrigChannelInfo->messageTtl >= MIN_SIGNALING_MESSAGE_TTL_VALUE && pOrigChannelInfo->messageTtl <= MAX_SIGNALING_MESSAGE_TTL_VALUE,
            STATUS_SIGNALING_INVALID_MESSAGE_TTL_VALUE);
    }

    // If tags count is not zero then pTags shouldn't be NULL
    CHK_STATUS(validateTags(pOrigChannelInfo->tagCount, pOrigChannelInfo->pTags));

    // Account for the tags
    CHK_STATUS(packageTags(pOrigChannelInfo->tagCount, pOrigChannelInfo->pTags, 0, NULL, &tagsSize));

    // Allocate enough storage to hold the data with aligned strings size and set the pointers and NULL terminators
    allocSize = SIZEOF(ChannelInfo) + ALIGN_UP_TO_MACHINE_WORD(1 + nameLen) + ALIGN_UP_TO_MACHINE_WORD(1 + arnLen) +
        ALIGN_UP_TO_MACHINE_WORD(1 + regionLen) + ALIGN_UP_TO_MACHINE_WORD(1 + cplLen) + ALIGN_UP_TO_MACHINE_WORD(1 + certLen) +
        ALIGN_UP_TO_MACHINE_WORD(1 + postfixLen) + ALIGN_UP_TO_MACHINE_WORD(1 + agentLen) + ALIGN_UP_TO_MACHINE_WORD(1 + userAgentLen) +
        ALIGN_UP_TO_MACHINE_WORD(1 + kmsLen) + tagsSize;
    CHK(NULL != (pChannelInfo = (PChannelInfo) MEMCALLOC(1, allocSize)), STATUS_NOT_ENOUGH_MEMORY);

    pChannelInfo->version = CHANNEL_INFO_CURRENT_VERSION;
    pChannelInfo->channelType = pOrigChannelInfo->channelType;
    pChannelInfo->channelRoleType = pOrigChannelInfo->channelRoleType;
    pChannelInfo->cachingPeriod = pOrigChannelInfo->cachingPeriod;
    pChannelInfo->retry = pOrigChannelInfo->retry;
    pChannelInfo->reconnect = pOrigChannelInfo->reconnect;
    pChannelInfo->messageTtl = pOrigChannelInfo->messageTtl;
    pChannelInfo->tagCount = pOrigChannelInfo->tagCount;

    // V1 handling
    if (pOrigChannelInfo->version > 0) {
        pChannelInfo->cachingPolicy = pOrigChannelInfo->cachingPolicy;
    } else {
        pChannelInfo->cachingPolicy = SIGNALING_API_CALL_CACHE_TYPE_NONE;
    }

    // Set the current pointer to the end
    pCurPtr = (PCHAR) (pChannelInfo + 1);

    // Set the pointers to the end and copy the data.
    // NOTE: the structure is calloc-ed so the strings will be NULL terminated
    if (nameLen != 0) {
        STRCPY(pCurPtr, pOrigChannelInfo->pChannelName);
        pChannelInfo->pChannelName = pCurPtr;
        pCurPtr += ALIGN_UP_TO_MACHINE_WORD(nameLen + 1); // For the NULL terminator
    }

    if (arnLen != 0) {
        STRCPY(pCurPtr, pOrigChannelInfo->pChannelArn);
        pChannelInfo->pChannelArn = pCurPtr;
        pCurPtr += ALIGN_UP_TO_MACHINE_WORD(arnLen + 1);
    }

    STRCPY(pCurPtr, pRegionPtr);
    pChannelInfo->pRegion = pCurPtr;
    pCurPtr += ALIGN_UP_TO_MACHINE_WORD(regionLen + 1);

    if (pOrigChannelInfo->pControlPlaneUrl != NULL && *pOrigChannelInfo->pControlPlaneUrl != '\0') {
        STRCPY(pCurPtr, pOrigChannelInfo->pControlPlaneUrl);
    } else {
        // Create a fully qualified URI
        SNPRINTF(pCurPtr, MAX_CONTROL_PLANE_URI_CHAR_LEN, "%s%s.%s%s", CONTROL_PLANE_URI_PREFIX, KINESIS_VIDEO_SERVICE_NAME, pChannelInfo->pRegion,
                 CONTROL_PLANE_URI_POSTFIX);
    }

    pChannelInfo->pControlPlaneUrl = pCurPtr;
    pCurPtr += ALIGN_UP_TO_MACHINE_WORD(cplLen + 1);

    if (certLen != 0) {
        STRCPY(pCurPtr, pOrigChannelInfo->pCertPath);
        pChannelInfo->pCertPath = pCurPtr;
        pCurPtr += ALIGN_UP_TO_MACHINE_WORD(certLen + 1);
    }

    if (postfixLen != 0) {
        STRCPY(pCurPtr, pOrigChannelInfo->pUserAgentPostfix);
        pChannelInfo->pUserAgentPostfix = pCurPtr;
        pCurPtr += ALIGN_UP_TO_MACHINE_WORD(postfixLen + 1);
    }

    if (agentLen != 0) {
        STRCPY(pCurPtr, pOrigChannelInfo->pCustomUserAgent);
        pChannelInfo->pCustomUserAgent = pCurPtr;
        pCurPtr += ALIGN_UP_TO_MACHINE_WORD(agentLen + 1);
    }

    getUserAgentString(pOrigChannelInfo->pUserAgentPostfix, pOrigChannelInfo->pCustomUserAgent, MAX_USER_AGENT_LEN, pCurPtr);
    pChannelInfo->pUserAgent = pCurPtr;
    pChannelInfo->pUserAgent[MAX_USER_AGENT_LEN] = '\0';
    pCurPtr += ALIGN_UP_TO_MACHINE_WORD(userAgentLen + 1);

    if (kmsLen != 0) {
        STRCPY(pCurPtr, pOrigChannelInfo->pCustomUserAgent);
        pChannelInfo->pKmsKeyId = pCurPtr;
        pCurPtr += ALIGN_UP_TO_MACHINE_WORD(kmsLen + 1);
    }

    // Fix-up the caching period
    if (pChannelInfo->cachingPeriod == SIGNALING_API_CALL_CACHE_TTL_SENTINEL_VALUE) {
        pChannelInfo->cachingPeriod = SIGNALING_DEFAULT_API_CALL_CACHE_TTL;
    }

    // Process tags
    pChannelInfo->tagCount = pOrigChannelInfo->tagCount;
    if (pOrigChannelInfo->tagCount != 0) {
        pChannelInfo->pTags = (PTag) pCurPtr;

        // Package the tags after the structure
        CHK_STATUS(packageTags(pOrigChannelInfo->tagCount, pOrigChannelInfo->pTags, tagsSize, pChannelInfo->pTags, NULL));
    }

CleanUp:

    if (STATUS_FAILED(retStatus)) {
        freeChannelInfo(&pChannelInfo);
    }

    if (ppChannelInfo != NULL) {
        *ppChannelInfo = pChannelInfo;
    }

    LEAVES();
    return retStatus;
}