static int s_append_canonical_header()

in source/aws_signing.c [1092:1175]


static int s_append_canonical_header(
    struct aws_signing_state_aws *state,
    struct aws_signable_property_list_pair *header,
    const struct aws_byte_cursor *last_seen_header_name) {

    struct aws_byte_buf *canonical_header_buffer = &state->canonical_header_block;
    struct aws_byte_buf *signed_headers_buffer = &state->signed_headers;
    const uint8_t *to_lower_table = aws_lookup_table_to_lower_get();

    /*
     * Write to the signed_headers shared state for later use, copy
     * to canonical header buffer as well
     */
    if (last_seen_header_name == NULL ||
        aws_byte_cursor_compare_lookup(last_seen_header_name, &header->name, aws_lookup_table_to_lower_get()) != 0) {
        /*
         * The headers arrive in sorted order, so we know we've never seen this header before
         */
        if (last_seen_header_name) {
            /*
             * there's a previous header, add appropriate separator in both canonical header buffer
             * and signed headers buffer
             */
            if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, '\n')) {
                return AWS_OP_ERR;
            }

            if (aws_byte_buf_append_byte_dynamic(signed_headers_buffer, ';')) {
                return AWS_OP_ERR;
            }
        }

        /* add it to the signed headers buffer */
        if (s_append_with_lookup(signed_headers_buffer, &header->name, to_lower_table)) {
            return AWS_OP_ERR;
        }

        /* add it to the canonical header buffer */
        if (s_append_with_lookup(canonical_header_buffer, &header->name, to_lower_table)) {
            return AWS_OP_ERR;
        }

        if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, ':')) {
            return AWS_OP_ERR;
        }
    } else {
        /* we've seen this header before, add a comma before appending the value */
        if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, ',')) {
            return AWS_OP_ERR;
        }
    }

    /*
     * This is the unsafe, non-append write of the header value where consecutive whitespace
     * is squashed into a single space.  Since this can only shrink the value length and we've
     * already reserved enough to hold the value, we can do raw buffer writes safely without
     * worrying about capacity.
     */
    struct aws_byte_cursor trimmed_value = aws_byte_cursor_trim_pred(&header->value, s_is_space);

    /* raw, unsafe write loop */
    bool in_space = false;
    uint8_t *start_ptr = trimmed_value.ptr;
    uint8_t *end_ptr = trimmed_value.ptr + trimmed_value.len;
    uint8_t *dest_ptr = canonical_header_buffer->buffer + canonical_header_buffer->len;
    while (start_ptr < end_ptr) {
        uint8_t value = *start_ptr;
        bool is_space = s_is_space(value);
        if (is_space) {
            value = ' ';
        }

        if (!is_space || !in_space) {
            *dest_ptr++ = value;
            ++canonical_header_buffer->len;
        }

        in_space = is_space;

        ++start_ptr;
    }

    return AWS_OP_SUCCESS;
}