chromium/chrome/services/ipp_parser/public/cpp/ipp_converter.h

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_SERVICES_IPP_PARSER_PUBLIC_CPP_IPP_CONVERTER_H_
#define CHROME_SERVICES_IPP_PARSER_PUBLIC_CPP_IPP_CONVERTER_H_

#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/containers/span.h"
#include "chrome/services/ipp_parser/public/mojom/ipp_parser.mojom.h"
#include "printing/backend/cups_ipp_helper.h"

// This namespace is filled with helpful (conversion) functions for working with
// arbitrary byte buffers representing IPP requests.
//
// IPP(internet printing protocol) is build on top of HTTP, so most of the these
// deal with working with arbitrary HTTP requests. The Parse methods take an
// arbitrary buffer and attempt to parse out the asked-for HTTP field/s. The
// Build methods do the exact opposite, taking separate HTTP fields and building
// an arbitrary buffer containing them, reading for shipping.

namespace ipp_converter {

using HttpHeader = std::pair<std::string, std::string>;

// Carriage return; Http header-pair delimiter.
const char kCarriage[] = "\r\n";

// Defined IPP end-of-message sentinel.
const char kIppSentinel[] = "\x03";

// Request line converters
// Parses |status_line| into vector of 3, individual terms, returns empty
// Optional on failure.
std::optional<std::vector<std::string>> ParseRequestLine(
    std::string_view status_line);

// Builds valid HTTP Request line from input span of 3 |terms|, returns empty
// Optional on failure.
std::optional<std::vector<uint8_t>> BuildRequestLine(
    std::string_view method,
    std::string_view endpoint,
    std::string_view http_version);

// Headers converters
// Parsed |headers_slice| into vector of HTTP header name/value pairs.
// Returns empty Optional on failure.
std::optional<std::vector<HttpHeader>> ParseHeaders(
    std::string_view headers_slice);

// Builds valid HTTP headers from input vector of header name/value pairs.
// Returns empty Optional on failure.
std::optional<std::vector<uint8_t>> BuildHeaders(std::vector<HttpHeader> terms);

// IPP message converters
// Reads |ipp_slice| into wrapped ipp_t*, using libCUPS APIs.
// Returns nullptr on failure.
printing::ScopedIppPtr ParseIppMessage(base::span<const uint8_t> ipp_slice);

// Builds valid IPP message from |ipp|, using libCUPS APIs.
// Returns empty Optional on failure.
// Note: Does not take ownership of |ipp|.
std::optional<std::vector<uint8_t>> BuildIppMessage(ipp_t* ipp);

// Often used helper wrapping the above commands for building a complete IPP
// request. Overloaded for cases without ipp_data.
// Returns empty Optional on any failure.
std::optional<std::vector<uint8_t>> BuildIppRequest(
    std::string_view method,
    std::string_view endpoint,
    std::string_view http_version,
    std::vector<HttpHeader> terms,
    ipp_t* ipp,
    std::vector<uint8_t> ipp_data);
std::optional<std::vector<uint8_t>> BuildIppRequest(
    std::string_view method,
    std::string_view endpoint,
    std::string_view http_version,
    std::vector<HttpHeader> terms,
    ipp_t* ipp);

// Mojom converter for ipp_t objects, return nullptr on failure.
// Note: This function does not take ownership of |ipp|.
ipp_parser::mojom::IppMessagePtr ConvertIppToMojo(ipp_t* ipp);

}  // namespace ipp_converter

#endif  // CHROME_SERVICES_IPP_PARSER_PUBLIC_CPP_IPP_CONVERTER_H_