in src/client/src/AckParser.c [31:265]
STATUS parseFragmentAck(PKinesisVideoStream pKinesisVideoStream, UPLOAD_HANDLE uploadHandle, PCHAR ackSegment, UINT32 ackSegmentSize)
{
ENTERS();
STATUS retStatus = STATUS_SUCCESS;
UINT32 index = 0;
UINT32 level = 0;
CHAR curChar;
PKinesisVideoClient pKinesisVideoClient = NULL;
BOOL streamLocked = FALSE;
CHK(pKinesisVideoStream != NULL && ackSegment != NULL, STATUS_NULL_ARG);
// If ack segment is specified and ack segment size is 0 then we should get the C-string size
if (0 == ackSegmentSize) {
ackSegmentSize = (UINT32) STRNLEN(ackSegment, MAX_ACK_FRAGMENT_LEN);
} else {
CHK(ackSegmentSize <= MAX_ACK_FRAGMENT_LEN, STATUS_INVALID_ACK_SEGMENT_LEN);
}
pKinesisVideoClient = pKinesisVideoStream->pKinesisVideoClient;
pKinesisVideoClient->clientCallbacks.lockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoStream->base.lock);
streamLocked = TRUE;
// Set the upload handle
if (!IS_VALID_UPLOAD_HANDLE(pKinesisVideoStream->fragmentAckParser.uploadHandle)) {
pKinesisVideoStream->fragmentAckParser.uploadHandle = uploadHandle;
}
for (index = 0; index < ackSegmentSize; index++) {
curChar = ackSegment[index];
switch (pKinesisVideoStream->fragmentAckParser.state) {
case FRAGMENT_ACK_PARSER_STATE_START:
// Skip until the start of the segment
if (ACK_PARSER_OPEN_BRACE == curChar) {
// Move to segment start state
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_ACK_START;
}
break;
case FRAGMENT_ACK_PARSER_STATE_ACK_START:
// Skip until non-whitespace
if (!IS_WHITE_SPACE(curChar)) {
// We should have a quote
CHK(curChar == ACK_PARSER_QUOTE, STATUS_INVALID_ACK_KEY_START);
// Start the key state
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_KEY_START;
}
break;
case FRAGMENT_ACK_PARSER_STATE_KEY_START:
// Accumulate until end of string
if (curChar == ACK_PARSER_QUOTE) {
// End of key start - parse the key name
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos] = '\0';
pKinesisVideoStream->fragmentAckParser.curKeyName = getFragmentAckKeyName(pKinesisVideoStream->fragmentAckParser.accumulator);
// Move to delimiter state
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_DELIMITER;
// Reset the cur position of the accumulator
pKinesisVideoStream->fragmentAckParser.curPos = 0;
} else {
// Accumulate it
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos++] = curChar;
}
break;
case FRAGMENT_ACK_PARSER_STATE_DELIMITER:
// Skip whitespaces until the delimiter
if (!IS_WHITE_SPACE(curChar)) {
if (curChar == ACK_PARSER_DELIMITER) {
// Move to the body start state
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_BODY_START;
}
}
break;
case FRAGMENT_ACK_PARSER_STATE_BODY_START:
// Skip whitespaces until the body start indicator
if (!IS_WHITE_SPACE(curChar)) {
if (curChar == ACK_PARSER_OPEN_BRACE) {
// Set the nestedness level
level = 1;
// Move to the skip body end state
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_SKIP_BODY_BRACE_END;
} else if (curChar == ACK_PARSER_OPEN_BRACKET) {
// Set the nestedness level
level = 1;
// Move to the skip body end state
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_SKIP_BODY_BRACKET_END;
} else if (curChar == ACK_PARSER_QUOTE) {
// Move to text value type
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_TEXT_VALUE;
} else if (IS_ACK_START_OF_NUMERIC_VALUE(curChar)) {
// Push the cur char to the accumulator
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos++] = curChar;
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_NUMERIC_VALUE;
} else {
CHK(FALSE, STATUS_INVALID_ACK_INVALID_VALUE_START);
}
}
break;
case FRAGMENT_ACK_PARSER_STATE_TEXT_VALUE:
// Accumulate until next quote
if (curChar == ACK_PARSER_QUOTE) {
// Null terminate the string
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos] = '\0';
// Process the value
CHK_STATUS(processAckValue(&pKinesisVideoStream->fragmentAckParser));
// Skip until the end of the value
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_VALUE_END;
} else {
// Accumulate it
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos++] = curChar;
}
break;
case FRAGMENT_ACK_PARSER_STATE_NUMERIC_VALUE:
// Accumulate until delimitation
if (IS_WHITE_SPACE(curChar)) {
// Null terminate the string
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos] = '\0';
// Process the value
CHK_STATUS(processAckValue(&pKinesisVideoStream->fragmentAckParser));
// Skip until the end of the value
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_VALUE_END;
} else if (curChar == ACK_PARSER_COMMA) {
// Null terminate the string
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos] = '\0';
// Process the value
CHK_STATUS(processAckValue(&pKinesisVideoStream->fragmentAckParser));
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_VALUE_END;
} else if (curChar == ACK_PARSER_CLOSE_BRACE) {
// Null terminate the string
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos] = '\0';
// Process the value
CHK_STATUS(processAckValue(&pKinesisVideoStream->fragmentAckParser));
// Process the parsed ACK
CHK_STATUS(processParsedAck(pKinesisVideoStream));
} else if (curChar == ACK_PARSER_QUOTE || curChar == ACK_PARSER_OPEN_BRACE || curChar == ACK_PARSER_OPEN_BRACKET ||
curChar == ACK_PARSER_CLOSE_BRACKET || curChar == ACK_PARSER_DELIMITER) {
// Error condition
CHK(FALSE, STATUS_INVALID_ACK_INVALID_VALUE_END);
} else {
// Accumulate it
pKinesisVideoStream->fragmentAckParser.accumulator[pKinesisVideoStream->fragmentAckParser.curPos++] = curChar;
}
break;
case FRAGMENT_ACK_PARSER_STATE_SKIP_BODY_BRACE_END:
// Skipping until the end of the body
if (curChar == ACK_PARSER_OPEN_BRACE) {
level++;
} else if (curChar == ACK_PARSER_CLOSE_BRACE) {
level--;
}
if (0 == level) {
// Body skipped. Move to next state
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_VALUE_END;
}
break;
case FRAGMENT_ACK_PARSER_STATE_SKIP_BODY_BRACKET_END:
// Skipping until the end of the body
if (curChar == ACK_PARSER_OPEN_BRACKET) {
level++;
} else if (curChar == ACK_PARSER_CLOSE_BRACKET) {
level--;
}
if (0 == level) {
// Body skipped. Move to next state
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_VALUE_END;
}
break;
case FRAGMENT_ACK_PARSER_STATE_VALUE_END:
// End of the value
// Skip the whitespaces or comma
if (IS_WHITE_SPACE(curChar) || ACK_PARSER_COMMA == curChar) {
break;
}
// If it's a closing curly then we are done
if (ACK_PARSER_CLOSE_BRACE == curChar) {
// Process the parsed ACK
CHK_STATUS(processParsedAck(pKinesisVideoStream));
} else if (ACK_PARSER_QUOTE == curChar) {
// Start of the new key
pKinesisVideoStream->fragmentAckParser.state = FRAGMENT_ACK_PARSER_STATE_KEY_START;
} else {
// An error is detected
CHK(FALSE, STATUS_INVALID_ACK_KEY_START);
}
break;
}
}
CleanUp:
// Reset the parser on error
if (STATUS_FAILED(retStatus)) {
resetAckParserState(pKinesisVideoStream);
}
if (streamLocked) {
pKinesisVideoClient->clientCallbacks.unlockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoStream->base.lock);
}
LEAVES();
return retStatus;
}