ResponseCode DiscoverAction::ReadResponseFromNetwork()

in src/discovery/Discovery.cpp [80:215]


        ResponseCode DiscoverAction::ReadResponseFromNetwork(std::shared_ptr<NetworkConnection> p_network_connection,
                                                             util::String &sent_packet,
                                                             util::String &read_payload,
                                                             std::chrono::milliseconds max_response_wait_time) {
            ResponseCode rc;

            util::Vector<unsigned char> temp_buf;
            util::Vector<unsigned char> read_buf;

            bool received_crlf = false;
            size_t read_bytes = 0;

            auto max_wait = std::chrono::steady_clock::now() + max_response_wait_time;
            do {
                rc = ReadFromNetworkBuffer(p_network_connection, temp_buf, 1);

                if (ResponseCode::SUCCESS == rc) {
                    read_bytes++;
                    read_buf.push_back(temp_buf[0]);

                    if ((read_bytes > 1) && read_buf[read_bytes - 1] == '\n' && read_buf[read_bytes - 2] == '\r') {
                        received_crlf = true;
                    }
                }

                if (std::chrono::steady_clock::now() > max_wait) {
                    rc = ResponseCode::DISCOVER_ACTION_REQUEST_TIMED_OUT_ERROR;
                    break;
                }
            } while (!received_crlf);

            if (ResponseCode::SUCCESS != rc) {
                return rc;
            }

            received_crlf = false;
            read_bytes = 0;
            // Parse header
            util::String response_header(read_buf.begin(), read_buf.end());
            if (util::String::npos == response_header.find(DISCOVER_ACTION_EXPECTED_SUCCESS_RESPONSE)) {
                if (util::String::npos != response_header.find(DISCOVER_ACTION_FAIL_INFO_NOT_PRESENT)) {
                    return ResponseCode::DISCOVER_ACTION_NO_INFORMATION_PRESENT;
                } else if (util::String::npos != response_header.find(DISCOVER_ACTION_FAIL_TOO_MANY_REQUESTS)) {
                    return ResponseCode::DISCOVER_ACTION_REQUEST_OVERLOAD;
                } else if (util::String::npos != response_header.find(DISCOVER_ACTION_FAIL_UNAUTHORIZED)) {
                    return ResponseCode::DISCOVER_ACTION_UNAUTHORIZED;
                } else {
                    AWS_LOG_ERROR(DISCOVER_LOG_TAG, "Discover Action HTTP request failed with a Response Header : \n%s",
                                  response_header.c_str());
                    return ResponseCode::DISCOVER_ACTION_SERVER_ERROR;
                }
            }

            util::String content_length_string(HTTP_CONTENT_LENGTH_STRING);
            size_t content_length_index = std::string::npos;
            read_buf.clear();
            do {
                rc = ReadFromNetworkBuffer(p_network_connection, temp_buf, 1);
                if (ResponseCode::SUCCESS != rc) {
                    break;
                }

                read_bytes++;
                read_buf.push_back(temp_buf[0]);

                if ((read_bytes > 1) && read_buf[read_bytes - 1] == '\n' && read_buf[read_bytes - 2] == '\r') {
                    util::String header_line(read_buf.begin(), read_buf.end());
                    content_length_index = header_line.find(content_length_string);
                    if (util::String::npos == content_length_index) {
                        read_buf.clear();
                        read_bytes = 0;
                        continue;
                    }
                    received_crlf = true;
                }

                if (std::chrono::steady_clock::now() > max_wait) {
                    rc = ResponseCode::DISCOVER_ACTION_REQUEST_TIMED_OUT_ERROR;
                    break;
                }
            } while (!received_crlf);

            if (content_length_index == std::string::npos) {
                if (ResponseCode::SUCCESS != rc) {
                    return rc;
                }
                return ResponseCode::DISCOVER_ACTION_NO_INFORMATION_PRESENT;
            }

            size_t content_length_begin_offset = content_length_index + content_length_string.length();
            size_t content_length_end_offset = content_length_begin_offset;
            while ('\r' != (char) read_buf[content_length_end_offset]) {
                content_length_end_offset++;
            }
            util::String content_length_str
                (read_buf.begin() + content_length_begin_offset, read_buf.begin() + content_length_end_offset);
            size_t content_length = std::stoul(content_length_str);

            // Skip the rest of the header
            received_crlf = false;
            do {
                rc = ReadFromNetworkBuffer(p_network_connection, temp_buf, 1);
                if (ResponseCode::SUCCESS != rc) {
                    break;
                }

                read_bytes++;
                read_buf.push_back(temp_buf[0]);

                if ((read_bytes > 1) && read_buf[read_bytes - 1] == '\n' && read_buf[read_bytes - 2] == '\r'
                    && read_buf[read_bytes - 3] == '\n' && read_buf[read_bytes - 4] == '\r') {
                    received_crlf = true;
                }

                if (std::chrono::steady_clock::now() > max_wait) {
                    rc = ResponseCode::DISCOVER_ACTION_REQUEST_TIMED_OUT_ERROR;
                    break;
                }
            } while (!received_crlf);

            read_buf.clear();

            if (0 < content_length) {
                rc = ReadFromNetworkBuffer(p_network_connection, read_buf, content_length);
                if (ResponseCode::SUCCESS == rc) {
                    read_payload.append(read_buf.begin(), read_buf.end());
                    size_t received_len = read_payload.length();
                    IOT_UNUSED(received_len);
                    read_buf.clear();
                }
            } else {
                rc = ResponseCode::DISCOVER_ACTION_REQUEST_FAILED_ERROR;
            }

            return rc;
        }