Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: third_party/cacheinvalidation/src/google/cacheinvalidation/impl/ticl-message-validator.cc

Issue 1162033004: Pull cacheinvalidations code directory into chromium repo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/cacheinvalidation/src/google/cacheinvalidation/impl/ticl-message-validator.cc
diff --git a/third_party/cacheinvalidation/src/google/cacheinvalidation/impl/ticl-message-validator.cc b/third_party/cacheinvalidation/src/google/cacheinvalidation/impl/ticl-message-validator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9a602cb8690bdd05de7a96579dba8bdf2a8fb802
--- /dev/null
+++ b/third_party/cacheinvalidation/src/google/cacheinvalidation/impl/ticl-message-validator.cc
@@ -0,0 +1,369 @@
+// Copyright 2012 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Validator for v2 protocol messages.
+
+#include "google/cacheinvalidation/impl/ticl-message-validator.h"
+
+#include "google/cacheinvalidation/impl/log-macro.h"
+#include "google/cacheinvalidation/impl/proto-helpers.h"
+#include "google/cacheinvalidation/include/system-resources.h"
+
+namespace invalidation {
+
+// High-level design: validation works via the collaboration of a set of macros
+// and template method specializations that obey a specific protocol. A
+// validator for a particular type is defined by a specialization of the method:
+//
+// template<typename T>
+// void TiclMessageValidator::Validate(const T& message, bool* result);
+//
+// A macro, DEFINE_VALIDATOR(type) is defined below to help prevent mistakes in
+// these definitions and to improve code readability. For example, to define
+// the validator for the type ObjectIdP, we'd write:
+//
+// DEFINE_VALIDATOR(ObjectIdP) { /* validation constraints ... */ }
+//
+// The choice of the names |message| and |result| is significant, as many of the
+// macros assume that these refer respectively to the message being validated
+// and the address in which the validation result is to be stored.
+//
+// When a validator is called, |*result| is initially |true|. To reject the
+// message, the validator sets |*result| to |false| and returns. Otherwise, it
+// simply allows control flow to continue; if no reason is found to reject the
+// message, control eventually returns to the caller with |*result| still set to
+// |true|, indicating that the message is acceptable. This protocol keeps the
+// bodies of the validation methods clean--otherwise they would all need need to
+// end with explicit |return| statements.
+//
+// A validator typically consists of a collection of constraints, at least one
+// per field in the message. Several macros are defined for common constraints,
+// including:
+//
+// REQUIRE(field): requires that (optional) |field| be present and valid.
+// ALLOW(field): allows (optional) |field| if valid.
+// ZERO_OR_MORE(field): validates each element of the (repeated) |field|.
+// ONE_OR_MORE(field): like ZERO_OR_MORE, but requires at least one element.
+// NON_EMPTY(field): checks that the string |field| is non-empty (if present).
+// NON_NEGATIVE(field): checks that the integral |field| is >= 0 (if present).
+//
+// For custom constraints, the CONDITION(expr) macro allows an arbitrary boolean
+// expression, which will generally refer to |message|.
+//
+// Note that REQUIRE, ALLOW, ZERO_OR_MORE, and ONE_OR_MORE all perform recursive
+// validation of the mentioned fields. A validation method must therefore be
+// defined for the type of the field, or there will be a link-time error.
+
+
+// Macros:
+
+// Macro to define a specialization of the |Validate| method for the given
+// |type|. This must be followed by a method body in curly braces defining
+// constraints on |message|, which is bound to a value of the given type. If
+// |message| is valid, no action is necessary; if invalid, a diagnostic message
+// should be logged via |logger_|, and |*result| should be set to false.
+#define DEFINE_VALIDATOR(type) \
+ template<> \
+ void TiclMessageValidator::Validate(const type& message, bool* result)
+
+// Expands into a conditional that checks whether |field| is present in
+// |message| and valid.
+#define REQUIRE(field) \
+ if (!message.has_##field()) { \
+ TLOG(logger_, SEVERE, "required field " #field " missing from %s", \
+ ProtoHelpers::ToString(message).c_str()); \
+ *result = false; \
+ return; \
+ } \
+ ALLOW(field);
+
+// Expands into a conditional that checks whether |field| is present in
+// |message|. If so, validates |message.field()|; otherwise, does nothing.
+#define ALLOW(field) \
+ if (message.has_##field()) { \
+ Validate(message.field(), result); \
+ if (!*result) { \
+ TLOG(logger_, SEVERE, "field " #field " failed validation in %s", \
+ ProtoHelpers::ToString(message).c_str()); \
+ return; \
+ } \
+ }
+
+// Expands into a conditional that checks that, if |field| is present in
+// |message|, then it is greater than or equal to |value|.
+#define GREATER_OR_EQUAL(field, value) \
+ if (message.has_##field() && (message.field() < value)) { \
+ TLOG(logger_, SEVERE, \
+ #field " must be greater than or equal to %d; was %d", \
+ value, message.field()); \
+ *result = false; \
+ return; \
+ }
+
+// Expands into a conditional that checks that, if the specified numeric |field|
+// is present, that it is non-negative.
+#define NON_NEGATIVE(field) GREATER_OR_EQUAL(field, 0)
+
+// Expands into a conditional that checks that, if the specified string |field|
+// is present, that it is non-empty.
+#define NON_EMPTY(field) \
+ if (message.has_##field() && message.field().empty()) { \
+ TLOG(logger_, SEVERE, #field " must be non-empty"); \
+ *result = false; \
+ return; \
+ }
+
+// Expands into a loop that checks that all elements of the repeated |field| are
+// valid.
+#define ZERO_OR_MORE(field) \
+ for (int i = 0; i < message.field##_size(); ++i) { \
+ Validate(message.field(i), result); \
+ if (!*result) { \
+ TLOG(logger_, SEVERE, "field " #field " #%d failed validation in %s", \
+ i, ProtoHelpers::ToString(message).c_str()); \
+ *result = false; \
+ return; \
+ } \
+ }
+
+// Expands into a loop that checks that there is at least one element of the
+// repeated |field|, and that all are valid.
+#define ONE_OR_MORE(field) \
+ if (message.field##_size() == 0) { \
+ TLOG(logger_, SEVERE, "at least one " #field " required in %s", \
+ ProtoHelpers::ToString(message).c_str()); \
+ *result = false; \
+ return; \
+ } \
+ ZERO_OR_MORE(field)
+
+// Expands into code that checks that the arbitrary condition |expr| is true.
+#define CONDITION(expr) \
+ *result = expr; \
+ if (!*result) { \
+ TLOG(logger_, SEVERE, #expr " not satisfied by %s", \
+ ProtoHelpers::ToString(message).c_str()); \
+ return; \
+ }
+
+
+// Validators:
+
+// No constraints on primitive types by default.
+DEFINE_VALIDATOR(bool) {}
+DEFINE_VALIDATOR(int) {}
+DEFINE_VALIDATOR(int64) {}
+DEFINE_VALIDATOR(string) {}
+
+// Similarly, for now enum values are always considered valid.
+DEFINE_VALIDATOR(ErrorMessage::Code) {}
+DEFINE_VALIDATOR(InfoRequestMessage::InfoType) {}
+DEFINE_VALIDATOR(InitializeMessage::DigestSerializationType) {}
+DEFINE_VALIDATOR(RegistrationP::OpType) {}
+DEFINE_VALIDATOR(StatusP::Code) {}
+
+DEFINE_VALIDATOR(Version) {
+ REQUIRE(major_version);
+ NON_NEGATIVE(major_version);
+ REQUIRE(minor_version);
+ NON_NEGATIVE(minor_version);
+}
+
+DEFINE_VALIDATOR(ProtocolVersion) {
+ REQUIRE(version);
+}
+
+DEFINE_VALIDATOR(ObjectIdP) {
+ REQUIRE(name);
+ REQUIRE(source);
+ NON_NEGATIVE(source);
+}
+
+DEFINE_VALIDATOR(InvalidationP) {
+ REQUIRE(object_id);
+ REQUIRE(is_known_version);
+ REQUIRE(version);
+ NON_NEGATIVE(version);
+ ALLOW(payload);
+}
+
+DEFINE_VALIDATOR(RegistrationP) {
+ REQUIRE(object_id);
+ REQUIRE(op_type);
+}
+
+DEFINE_VALIDATOR(RegistrationSummary) {
+ REQUIRE(num_registrations);
+ NON_NEGATIVE(num_registrations);
+ REQUIRE(registration_digest);
+ NON_EMPTY(registration_digest);
+}
+
+DEFINE_VALIDATOR(InvalidationMessage) {
+ ONE_OR_MORE(invalidation);
+}
+
+DEFINE_VALIDATOR(ClientHeader) {
+ REQUIRE(protocol_version);
+ ALLOW(client_token);
+ NON_EMPTY(client_token);
+ ALLOW(registration_summary);
+ REQUIRE(client_time_ms);
+ REQUIRE(max_known_server_time_ms);
+ ALLOW(message_id);
+ ALLOW(client_type);
+}
+
+DEFINE_VALIDATOR(ApplicationClientIdP) {
+ REQUIRE(client_type);
+ REQUIRE(client_name);
+ NON_EMPTY(client_name);
+}
+
+DEFINE_VALIDATOR(InitializeMessage) {
+ REQUIRE(client_type);
+ REQUIRE(nonce);
+ NON_EMPTY(nonce);
+ REQUIRE(digest_serialization_type);
+ REQUIRE(application_client_id);
+}
+
+DEFINE_VALIDATOR(RegistrationMessage) {
+ ONE_OR_MORE(registration);
+}
+
+DEFINE_VALIDATOR(ClientVersion) {
+ REQUIRE(version);
+ REQUIRE(platform);
+ REQUIRE(language);
+ REQUIRE(application_info);
+}
+
+DEFINE_VALIDATOR(PropertyRecord) {
+ REQUIRE(name);
+ REQUIRE(value);
+}
+
+DEFINE_VALIDATOR(RateLimitP) {
+ REQUIRE(window_ms);
+ GREATER_OR_EQUAL(window_ms, 1000);
+ CONDITION(message.window_ms() > message.count());
+ REQUIRE(count);
+}
+
+DEFINE_VALIDATOR(ProtocolHandlerConfigP) {
+ ALLOW(batching_delay_ms);
+ ZERO_OR_MORE(rate_limit);
+}
+
+DEFINE_VALIDATOR(ClientConfigP) {
+ REQUIRE(version);
+ ALLOW(network_timeout_delay_ms);
+ ALLOW(write_retry_delay_ms);
+ ALLOW(heartbeat_interval_ms);
+ ALLOW(perf_counter_delay_ms);
+ ALLOW(max_exponential_backoff_factor);
+ ALLOW(smear_percent);
+ ALLOW(is_transient);
+ ALLOW(initial_persistent_heartbeat_delay_ms);
+ ALLOW(channel_supports_offline_delivery);
+ REQUIRE(protocol_handler_config);
+ ALLOW(offline_heartbeat_threshold_ms);
+ ALLOW(allow_suppression);
+}
+
+DEFINE_VALIDATOR(InfoMessage) {
+ REQUIRE(client_version);
+ ZERO_OR_MORE(config_parameter);
+ ZERO_OR_MORE(performance_counter);
+ ALLOW(client_config);
+ ALLOW(server_registration_summary_requested);
+}
+
+DEFINE_VALIDATOR(RegistrationSubtree) {
+ ZERO_OR_MORE(registered_object);
+}
+
+DEFINE_VALIDATOR(RegistrationSyncMessage) {
+ ONE_OR_MORE(subtree);
+}
+
+DEFINE_VALIDATOR(ClientToServerMessage) {
+ REQUIRE(header);
+ ALLOW(info_message);
+ ALLOW(initialize_message);
+ ALLOW(invalidation_ack_message);
+ ALLOW(registration_message);
+ ALLOW(registration_sync_message);
+ CONDITION(message.has_initialize_message() ^
+ message.header().has_client_token());
+}
+
+DEFINE_VALIDATOR(ServerHeader) {
+ REQUIRE(protocol_version);
+ REQUIRE(client_token);
+ NON_EMPTY(client_token);
+ ALLOW(registration_summary);
+ REQUIRE(server_time_ms);
+ NON_NEGATIVE(server_time_ms);
+ ALLOW(message_id);
+ NON_EMPTY(message_id);
+}
+
+DEFINE_VALIDATOR(StatusP) {
+ REQUIRE(code);
+ ALLOW(description);
+}
+
+DEFINE_VALIDATOR(TokenControlMessage) {
+ ALLOW(new_token);
+}
+
+DEFINE_VALIDATOR(ErrorMessage) {
+ REQUIRE(code);
+ REQUIRE(description);
+}
+
+DEFINE_VALIDATOR(RegistrationStatus) {
+ REQUIRE(registration);
+ REQUIRE(status);
+}
+
+DEFINE_VALIDATOR(RegistrationStatusMessage) {
+ ONE_OR_MORE(registration_status);
+}
+
+DEFINE_VALIDATOR(RegistrationSyncRequestMessage) {}
+
+DEFINE_VALIDATOR(InfoRequestMessage) {
+ ONE_OR_MORE(info_type);
+}
+
+DEFINE_VALIDATOR(ConfigChangeMessage) {
+ ALLOW(next_message_delay_ms);
+ GREATER_OR_EQUAL(next_message_delay_ms, 1);
+}
+
+DEFINE_VALIDATOR(ServerToClientMessage) {
+ REQUIRE(header);
+ ALLOW(token_control_message);
+ ALLOW(invalidation_message);
+ ALLOW(registration_status_message);
+ ALLOW(registration_sync_request_message);
+ ALLOW(config_change_message);
+ ALLOW(info_request_message);
+ ALLOW(error_message);
+}
+
+} // namespace invalidation

Powered by Google App Engine
This is Rietveld 408576698