-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathframe.h
185 lines (165 loc) · 7.56 KB
/
frame.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIBIPP_FRAME_H_
#define LIBIPP_FRAME_H_
#include <array>
#include <cstdint>
#include <utility>
#include <vector>
#include "attribute.h"
#include "colls_view.h"
#include "ipp_enums.h"
#include "ipp_export.h"
namespace ipp {
// represents operation id
typedef E_operations_supported Operation;
// represents status-code [rfc8010]
typedef E_status_code Status;
// represents the version of IPP protocol
// The first byte (MSB) of this value correspond to major version number, the
// second one to minor version number.
typedef E_ipp_versions_supported Version;
// There are methods that return error codes. The error code is usually
// returned via the last method's parameter that is optional.
// This enum contains possible values of error codes.
enum class Code {
kOK, // success (no errors)
kDataTooLong, // the payload of the frame is too large
kInvalidGroupTag, // provided GroupTag is invalid
kInvalidValueTag, // provided ValueTag is invalid
kIndexOutOfRange, // parameter 'index' is wrong
kTooManyGroups, // reached the threshold
kTooManyAttributes, // reached the threshold
kInvalidName, // incorrect attribute name
kNameConflict, // attribute with this name already exists
kIncompatibleType, // conversion between C++ type and value is not supported
kValueOutOfRange // given C++ value is out of range (invalid)
};
// The correct values of GroupTag are 0x01, 0x02, 0x04-0x0f. This function
// checks if given GroupTag is valid.
constexpr bool IsValid(GroupTag tag) {
if (tag > static_cast<GroupTag>(0x0f))
return false;
if (tag < static_cast<GroupTag>(0x01))
return false;
return (tag != static_cast<GroupTag>(0x03));
}
// This array contains all valid GroupTag values and may be used in loops like
// for (GroupTag gt: kGroupTags) ...
constexpr std::array<GroupTag, 14> kGroupTags{
static_cast<GroupTag>(0x01), static_cast<GroupTag>(0x02),
static_cast<GroupTag>(0x04), static_cast<GroupTag>(0x05),
static_cast<GroupTag>(0x06), static_cast<GroupTag>(0x07),
static_cast<GroupTag>(0x08), static_cast<GroupTag>(0x09),
static_cast<GroupTag>(0x0a), static_cast<GroupTag>(0x0b),
static_cast<GroupTag>(0x0c), static_cast<GroupTag>(0x0d),
static_cast<GroupTag>(0x0e), static_cast<GroupTag>(0x0f)};
// TODO(pawliczek) - move all limits to separate header, this one was moved here
// from ipp_parser.cc
// This parameters defines maximum number of attribute groups in single package.
constexpr size_t kMaxCountOfAttributeGroups = 20 * 1024;
class Collection;
class Attribute;
// This class represents an IPP frame (IPP request or IPP response). All
// pointers to Collection or Attribute returned by methods of this class
// point to internal objects. These objects are always owned by their Frame
// object and their lifetime does not exceed the lifetime of their owner.
class LIBIPP_EXPORT Frame {
public:
// Constructor. Create an empty frame with all basic parameters set to 0.
Frame();
// Constructor. Create a frame and set basic parameters for IPP request.
// If `set_localization_en_us` is true (default) the Group Operation
// Attributes is added to the frame with two attributes:
// * "attributes-charset"="utf-8"
// * "attributes-natural-language"="en-us"
// If `set_localization_en_us` equals false, you have to add the Group
// Operation Attributes with these two attributes by hand since they are
// required to be the first attributes in the frame (see section 4.1.4 from
// RFC 8011).
explicit Frame(Operation operation_id,
Version version_number = Version::_1_1,
int32_t request_id = 1,
bool set_localization_en_us = true);
// Constructor. The same as the previous constructor but for IPP response.
// There is no differences between frames created with this and the previous
// constructor. IPP requests and IPP responses have the same structure.
// Values of operation_id and status_code are saved in the same variable,
// they are just casted to different enums with static_cast<>(). The parameter
// `set_localization_en_us_and_status_message` works in similar way as the
// parameter `set_localization_en_us` in the constructor above but also adds
// the attribute "status-message" to the Group Operation Attributes. The value
// of the attribute is set to a string representation of the `status_code`.
// The attribute "status-message" is defined in the section 4.1.6.2 from
// RFC 8011.
explicit Frame(Status status_code,
Version version_number = Version::_1_1,
int32_t request_id = 1,
bool set_localization_en_us_and_status_message = true);
Frame(const Frame&) = delete;
Frame& operator=(const Frame&) = delete;
Frame(Frame&&) = default;
Frame& operator=(Frame&&) = default;
virtual ~Frame();
// Access IPP version number.
Version& VersionNumber();
Version VersionNumber() const;
// Access operation id or status code. OperationId() and StatusCode() refer to
// the same field, they just cast the same value to different enums. The field
// is interpreted as operation id in IPP request and as status code in IPP
// responses.
int16_t& OperationIdOrStatusCode();
int16_t OperationIdOrStatusCode() const;
Operation OperationId() const;
Status StatusCode() const;
// Access request id.
int32_t& RequestId();
int32_t RequestId() const;
// Access to payload (e.g.: document to print).
const std::vector<uint8_t>& Data() const;
// Remove the payload from the frame and return it.
std::vector<uint8_t> TakeData();
// Set the new payload in the frame. The returned value is one of:
// * Code::kOK
// * Code::kDataTooLong
Code SetData(std::vector<uint8_t>&& data);
// Provides access to groups with the given GroupTag. You can iterate over
// these groups in the following way:
// for (Collection& coll: frame.Groups(GroupTag::job_attributes)) {
// ...
// }
// or
// for (size_t i = 0; i < frame.Groups(GroupTag::job_attributes).size(); ) {
// Collection& coll = frame.Groups(GroupTag::job_attributes)[i++];
// ...
// }
// The groups are in the same order as they occur in the frame.
CollsView Groups(GroupTag tag);
ConstCollsView Groups(GroupTag tag) const;
// Return all groups of attributes in the frame in the order they were added.
// The returned vector never contains nullptr values.
std::vector<std::pair<GroupTag, Collection*>> GetGroups();
std::vector<std::pair<GroupTag, const Collection*>> GetGroups() const;
// Add a new group of attributes to the frame. The iterator to the new group
// is saved in `new_group`. The returned iterator is valid in the range
// returned by Groups(tag).
// The returned value is one of the following:
// * Code::kOK
// * Code::kInvalidGroupTag
// * Code::kTooManyGroups
// If the returned value != Code::kOK then `new_group` is not modified.
Code AddGroup(GroupTag tag, CollsView::iterator& new_group);
private:
Version version_;
int16_t operation_id_or_status_code_;
int32_t request_id_;
// Groups stored in the order they appear in the binary representation.
std::vector<std::pair<GroupTag, Collection*>> groups_;
// Content of `group_` sorted by GroupTag. The largest valid value of GroupTag
// is 0x0f (see kGroupTags above).
std::array<std::vector<Collection*>, 16> groups_by_tag_;
std::vector<uint8_t> data_;
};
} // namespace ipp
#endif // LIBIPP_FRAME_H_