in HAP/HAPIPAccessoryServer.c [3075:3182]
static void read_http(HAPIPSessionDescriptor* session) {
HAPPrecondition(session);
HAPPrecondition(session->server);
struct util_http_reader* r;
HAPAssert(session->inboundBuffer.data);
HAPAssert(session->inboundBuffer.position <= session->inboundBuffer.limit);
HAPAssert(session->inboundBuffer.limit <= session->inboundBuffer.capacity);
HAPAssert(session->httpReaderPosition <= session->inboundBuffer.position);
HAPAssert(!session->httpParserError);
r = &session->httpReader;
bool hasContentLength = false;
bool hasContentType = false;
do {
session->httpReaderPosition += util_http_reader_read(
r,
&session->inboundBuffer.data[session->httpReaderPosition],
session->inboundBuffer.position - session->httpReaderPosition);
switch (r->state) {
case util_HTTP_READER_STATE_READING_METHOD:
case util_HTTP_READER_STATE_COMPLETED_METHOD: {
update_token(r, &session->httpMethod.bytes, &session->httpMethod.numBytes);
} break;
case util_HTTP_READER_STATE_READING_URI:
case util_HTTP_READER_STATE_COMPLETED_URI: {
update_token(r, &session->httpURI.bytes, &session->httpURI.numBytes);
} break;
case util_HTTP_READER_STATE_READING_HEADER_NAME:
case util_HTTP_READER_STATE_COMPLETED_HEADER_NAME: {
update_token(r, &session->httpHeaderFieldName.bytes, &session->httpHeaderFieldName.numBytes);
} break;
case util_HTTP_READER_STATE_READING_HEADER_VALUE: {
update_token(r, &session->httpHeaderFieldValue.bytes, &session->httpHeaderFieldValue.numBytes);
} break;
case util_HTTP_READER_STATE_COMPLETED_HEADER_VALUE: {
update_token(r, &session->httpHeaderFieldValue.bytes, &session->httpHeaderFieldValue.numBytes);
HAPAssert(session->httpHeaderFieldName.bytes);
if ((session->httpHeaderFieldName.numBytes == 14) &&
(session->httpHeaderFieldName.bytes[0] == 'C' || session->httpHeaderFieldName.bytes[0] == 'c') &&
(session->httpHeaderFieldName.bytes[1] == 'O' || session->httpHeaderFieldName.bytes[1] == 'o') &&
(session->httpHeaderFieldName.bytes[2] == 'N' || session->httpHeaderFieldName.bytes[2] == 'n') &&
(session->httpHeaderFieldName.bytes[3] == 'T' || session->httpHeaderFieldName.bytes[3] == 't') &&
(session->httpHeaderFieldName.bytes[4] == 'E' || session->httpHeaderFieldName.bytes[4] == 'e') &&
(session->httpHeaderFieldName.bytes[5] == 'N' || session->httpHeaderFieldName.bytes[5] == 'n') &&
(session->httpHeaderFieldName.bytes[6] == 'T' || session->httpHeaderFieldName.bytes[6] == 't') &&
(session->httpHeaderFieldName.bytes[7] == '-') &&
(session->httpHeaderFieldName.bytes[8] == 'L' || session->httpHeaderFieldName.bytes[8] == 'l') &&
(session->httpHeaderFieldName.bytes[9] == 'E' || session->httpHeaderFieldName.bytes[9] == 'e') &&
(session->httpHeaderFieldName.bytes[10] == 'N' || session->httpHeaderFieldName.bytes[10] == 'n') &&
(session->httpHeaderFieldName.bytes[11] == 'G' || session->httpHeaderFieldName.bytes[11] == 'g') &&
(session->httpHeaderFieldName.bytes[12] == 'T' || session->httpHeaderFieldName.bytes[12] == 't') &&
(session->httpHeaderFieldName.bytes[13] == 'H' || session->httpHeaderFieldName.bytes[13] == 'h')) {
if (hasContentLength) {
HAPLog(&logObject, "Request has multiple Content-Length headers.");
session->httpParserError = true;
} else {
hasContentLength = true;
read_http_content_length(session);
}
} else if (
(session->httpHeaderFieldName.numBytes == 12) &&
(session->httpHeaderFieldName.bytes[0] == 'C' ||
session->httpHeaderFieldName.bytes[0] == 'c') &&
(session->httpHeaderFieldName.bytes[1] == 'O' ||
session->httpHeaderFieldName.bytes[1] == 'o') &&
(session->httpHeaderFieldName.bytes[2] == 'N' ||
session->httpHeaderFieldName.bytes[2] == 'n') &&
(session->httpHeaderFieldName.bytes[3] == 'T' ||
session->httpHeaderFieldName.bytes[3] == 't') &&
(session->httpHeaderFieldName.bytes[4] == 'E' ||
session->httpHeaderFieldName.bytes[4] == 'e') &&
(session->httpHeaderFieldName.bytes[5] == 'N' ||
session->httpHeaderFieldName.bytes[5] == 'n') &&
(session->httpHeaderFieldName.bytes[6] == 'T' ||
session->httpHeaderFieldName.bytes[6] == 't') &&
(session->httpHeaderFieldName.bytes[7] == '-') &&
(session->httpHeaderFieldName.bytes[8] == 'T' ||
session->httpHeaderFieldName.bytes[8] == 't') &&
(session->httpHeaderFieldName.bytes[9] == 'Y' ||
session->httpHeaderFieldName.bytes[9] == 'y') &&
(session->httpHeaderFieldName.bytes[10] == 'P' ||
session->httpHeaderFieldName.bytes[10] == 'p') &&
(session->httpHeaderFieldName.bytes[11] == 'E' ||
session->httpHeaderFieldName.bytes[11] == 'e')) {
if (hasContentType) {
HAPLog(&logObject, "Request has multiple Content-Type headers.");
session->httpParserError = true;
} else {
hasContentType = true;
read_http_content_type(session);
}
}
session->httpHeaderFieldName.bytes = NULL;
session->httpHeaderFieldValue.bytes = NULL;
} break;
default: {
} break;
}
} while ((session->httpReaderPosition < session->inboundBuffer.position) &&
(r->state != util_HTTP_READER_STATE_DONE) && (r->state != util_HTTP_READER_STATE_ERROR) &&
!session->httpParserError);
HAPAssert(
(session->httpReaderPosition == session->inboundBuffer.position) ||
((session->httpReaderPosition < session->inboundBuffer.position) &&
((r->state == util_HTTP_READER_STATE_DONE) || (r->state == util_HTTP_READER_STATE_ERROR) ||
session->httpParserError)));
}