blob: 285457d61d600fd71bfb468401b770443fa9f631 [file] [log] [blame]
// Copyright 2011 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.
// Specification of protocol buffers and the client-server protocol that are
// used by the clients of the system.
//
// Note: unless otherwise specified in a comment, all fields in all messages
// are required, even though they are listed as optional.
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package ipc.invalidation;
// Here is a high-level overview of the protocol. The protocol is designed in a
// "message-passing" style, i.e., the client (C) or the server (S) can send any
// message SPONTANEOUSLY at any time and both sides have to be prepared for any
// message from the other side. However, even with this style, there are some
// "flows" which are somewhat like requests and replies.
// 1. Initialization: When a client starts up, it needs a token to alow it to
// perform any other operation with the server.
// C -> S: InitializeMessage
// S -> C: TokenControlMessage
//
// 2. Registration: When a client has to register or unregister for a set of
// objects, the following flow occurs:
// C -> S: RegistrationMessage
// S -> C: RegistrationStatusMessage
//
// 3. Invalidation: The server sends an invalidation and the client sends back
// an ack.
// S -> C InvalidationMessage
// C -> S InvalidationMessage
//
// 4. Registration sync: Once in a while the server may detect that the client
// and server's registration state is out of sync (the server can detect this
// since it gets the client's registration summary in the client's message
// header). In that case, it asks the client some registration information
// and the client sends it to the server.
// S -> C: RegistrationSyncRequestMessage
// C -> S: RegistrationSyncMessage
//
// 5. Information messages: The server can occasionally for client-side
// information such as statistics, etc. The client responds with the
// requested information
// S -> C: InfoRequestMessage
// C -> S: InfoMessage
//
// ------------------------------------------------------------------------
// A basic message type used for versioning public proto messages and/or
// types. The two fields are supposed to be used as follows:
//
// * The major version number is changed whenever an incompatible protocol
// change or type has been made. When a message/object with a particular
// major version is received, the receiver needs to either know how to handle
// this version or it needs to drop the message
//
// * The minor version can be changed (say) to document some internal change
// for debugging purposes. When a message is received by a receiver, it MUST
// ignore the minor version number for making any protocol/type
// decisions. I.e., the minor version number is for debugging purposes only.
//
// Versioning is used in various places - for entities that are part of a
// protocol (e.g., message requests), for various client implementations, and
// for other data types that change independently of the protocol (e.g.,
// session tokens). For each versioned entity, we define a specific message
// type to encapsulate the version of that entity (e.g., ProtocolVersion,
// ClientVersion, etc.).
message Version {
optional int32 major_version = 1;
optional int32 minor_version = 2;
}
// Message included in all client <-> server messages to indicate the version
// of the protocol in use by the sender.
message ProtocolVersion {
optional Version version = 1;
}
// Defines a specific version of the client library (for information purposes
// only) May not be used to make decisions at the server (use ProtocolVersion
// instead).
message ClientVersion {
// A client-specific version number.
optional Version version = 1;
// All fields below are for informational/debugging/monitoring purposes only.
// No critical code decision is supposed to be made using them.
// Information about the client operating system/platform, e.g., Windows,
// ChromeOS.
optional string platform = 2;
// Language used for the library.
optional string language = 3;
// Extra information about the client (e.g., application name).
optional string application_info = 4;
}
// Message indicating the result of an operation.
message StatusP {
// Whether operation is successful or not
enum Code {
SUCCESS = 1;
TRANSIENT_FAILURE = 2;
PERMANENT_FAILURE = 3;
}
optional Code code = 1;
// Textual description of the status or additional context about any
// error. (Optional - Can be set for success also.)
optional string description = 2;
}
// Identifies an object that a client can register for.
message ObjectIdP {
// The source of the data.
optional int32 source = 1;
// The id of the object relative to the source. Must be <= 64 bytes.
optional bytes name = 2;
}
// A message containing the part of the client's id that the application
// controls. This id is used for squelching invalidations on the server side.
// For example, if a client C1 modifies object x and informs the backend about
// C1's application client id as part of the invalidation. The backend can then
// avoid sending the invalidation unnecessarily to that client.
//
// If the application wishes to use this squelching feature, it must assign a
// globally unique client_name for a given client_type so that the particular
// instantation of the application can be identified.
message ApplicationClientIdP {
// The type of the client.
optional int32 client_type = 1;
// A client name or unique id assigned by the application. Application should
// choose a unique name for different client instances if it wants to squelch
// invalidations by name (as discussed above).
optional bytes client_name = 2;
}
// Invalidation for a given object/version.
message InvalidationP {
// The id of the object being invalidated.
optional ObjectIdP object_id = 1;
// Whether the invalidation is for a known version of the object as assigned
// by an application backend (is_known_version == true) or an unknown system
// version synthesized by the invalidation service. (Note that if
// is_known_version is false then is_trickle_restart be true or missing
// because an unknown version implies that invalidation versions prior to the
// current backend version may have been dropped.)
optional bool is_known_version = 2;
// Version being invalidated (see comment on is_known_version). If the
// is_known_version is false, the version corresponds to an internal "system
// version" for *that* object. An object's system version has no meaning to
// the application other than the fact that these system versions are also
// monotonically increasing and the client must ack such an invalidation with
// this system version (and an ack for a later system version acknowledges an
// invalidation for all earlier system version for *that* object.
optional int64 version = 3;
// Whether the object's Trickle is restarting at this version.
// sets this value to true to inform Trickle API clients that it may
// have dropped invalidations prior to "version", or, if is_known_version is
// false, prior to the current backend version.
optional bool is_trickle_restart = 6 [default = false];
// Optional payload associated with this invalidation.
optional bytes payload = 4;
// DEPRECATED: bridge arrival time is now maintained by
// InvalidationMetadataP in the SourcedInvalidation, InvalidationContents and
// ClientInvalidation containers.
optional int64 bridge_arrival_time_ms_deprecated = 5 [deprecated=true];
}
// Specifies the intention to change a registration on a specific object. To
// update registrations, a client sends a message containing repeated
// RegistrationP messages.
message RegistrationP {
enum OpType {
REGISTER = 1;
UNREGISTER = 2;
}
// The object for which to (un)register.
optional ObjectIdP object_id = 1;
// Whether to register or unregister.
optional OpType op_type = 2;
}
// Summary of the registration state associated with a particular client, sent
// in the header of client<->server messages. This summary has two different
// (but related) meanings depending on where it is used:
//
// 1) In a client->server message, it describes the DESIRED client state.
// 2) In a server->client message, it describes the ACTUAL state at the server
// for that client.
message RegistrationSummary {
// Number of registrations desired (client) or held (server).
optional int32 num_registrations = 1;
// Top-level digest over the registrations.
//
// The digest for an object id is computed as following (the digest chosen for
// this method is SHA-1):
//
// digest = new Digest();
// digest.update(Little endian encoding of object source type)
// digest.update(object name)
// digest.getDigestSummary()
//
// For a set of objects, digest is computing by sorting lexicographically
// based on their digests and then performing the update process given above
// (i.e., calling digest.update on each object's digest and then calling
// getDigestSummary at the end).
optional bytes registration_digest = 2;
}
// Header included on every client -> server message.
message ClientHeader {
// Protocol version of this message.
optional ProtocolVersion protocol_version = 1;
// Token identifying the client. Tokens are issued by the server in response
// to client requests (see InitializeMessage, below). In order to perform any
// operation other than initialization, the client must supply a token. When
// performing initialization, this field must be left unset.
optional bytes client_token = 2;
// Optional summary of the client's desired registration state. The client is
// encouraged to provide this summary in every message once a "steady" state
// of registrations/unregistrations has been reached. For example, it may not
// want to send this summary during initialization (but after the initial set
// has been registered, it should try to send it).
optional RegistrationSummary registration_summary = 3;
// Timestamp from the client's clock, expressed as ms since 00:00:00 UTC, 1
// January 1970 (i.e., the UNIX epoch) - for debugging/monitoring purposes.
optional int64 client_time_ms = 4;
// Highest server timestamp observed by the client (the server includes its
// time on every message to the client). Note: this time is NOT necessarily
// expressed as relative to the UNIX epoch - for debugging/monitoring
// purposes.
optional int64 max_known_server_time_ms = 5;
// Message id to identify the message -for debugging/monitoring purposes.
optional string message_id = 6;
// Client typecode (as in the InitializeMessage, below). This field may or
// may not be set.
optional int32 client_type = 7;
}
// A message from the client to the server.
message ClientToServerMessage {
// Header.
optional ClientHeader header = 1;
// Any or all of the follow messages may be present.
// Optional initialization message, used to obtain a new token. Note that, if
// present, this message is always processed before the messages below, and
// those messages will be interpreted relative to the new token assigned here.
optional InitializeMessage initialize_message = 2;
// Optional request to perform registrations.
optional RegistrationMessage registration_message = 3;
// Optional data for registration sync.
optional RegistrationSyncMessage registration_sync_message = 4;
// Optional invalidation acks.
optional InvalidationMessage invalidation_ack_message = 5;
// Optional information about the client.
optional InfoMessage info_message = 6;
}
// Used to obtain a new token when the client does not have one.
message InitializeMessage {
// Defines how clients serialize object ids when computing digests for
// registrations.
enum DigestSerializationType {
// The digest for an object id is computed by serializing the object id into
// bytes.
BYTE_BASED = 1;
// The digest for an object id is computed by serializing the object id into
// an array of numbers.
NUMBER_BASED = 2;
}
// Type of the client. This value is assigned by the backend notification
// system (out-of-band) and the client must use the correct value.
optional int32 client_type = 1;
// Nonce. This value will be echoed as the existing token in the header of
// the server message that supplies the new token (the new token itself will
// be provided in a TokenControlMessage; see below).
optional bytes nonce = 2;
// Id of the client as assigned by the application.
optional ApplicationClientIdP application_client_id = 3;
// Type of registration digest used by this client.
optional DigestSerializationType digest_serialization_type = 4;
}
// Registration operations to perform.
message RegistrationMessage {
repeated RegistrationP registration = 1;
}
// Message from the client to the server.
message RegistrationSyncMessage {
// Objects for which the client is registered.
repeated RegistrationSubtree subtree = 1;
}
// Message sent from the client to the server about registered objects
// (typically) in response to a registration sync request.
//
// The name of the message implies a "tree" for future expansion where the
// intention is to not necessarily send the complete set of objects but to
// partition the object space into multiple ranges and then exchange Merkle-tree
// like data structures to determine which ranges are out-of-sync.
message RegistrationSubtree {
// Registered objects
repeated ObjectIdP registered_object = 1;
}
// A message from the client to the server with info such as performance
// counters, client os info, etc.
message InfoMessage {
optional ClientVersion client_version = 1;
// Config parameters used by the client.
// Deprecated and removed - the client_config parameter is what is used now.
repeated PropertyRecord config_parameter = 2;
// Performance counters from the client.
repeated PropertyRecord performance_counter = 3;
// If 'true', indicates that the client does not know the server's
// registration summary, so the server should respond with it even if the
// client's summary matches the server's.
optional bool server_registration_summary_requested = 4;
// Configuration parameters for this client.
optional ClientConfigP client_config = 5;
}
// Information about a single config/performance counter value in the
// InfoMessage.
message PropertyRecord {
// Name of the performance counter/config parameter.
optional string name = 1;
// Value of the performance counter/config parameter.
optional int32 value = 2;
}
message ServerHeader {
// Protocol version of this message.
optional ProtocolVersion protocol_version = 1;
// Current token that the server expects the client to have. Clients must
// ignore messages where this token field does not match their current token.
// During initialization, the client's "token" is the nonce that it generates
// and sends in the InitializeMessage.
optional bytes client_token = 2;
// Summary of registration state held by the server for the client.
optional RegistrationSummary registration_summary = 3;
// Timestamp from the server's clock. No guarantee on when this time is
// relative to.
optional int64 server_time_ms = 4;
// Message id to identify the message (for debug purposes only).
optional string message_id = 5;
}
message ServerToClientMessage {
optional ServerHeader header = 1;
// Message to assign a new client token or invalidate an existing one. Note
// that, if present, this message is always processed before the messages
// below, and those messages will be interpreted relative to the new token
// assigned here.
optional TokenControlMessage token_control_message = 2;
// Invalidations.
optional InvalidationMessage invalidation_message = 3;
// Registration operation replies.
optional RegistrationStatusMessage registration_status_message = 4;
// Request for client registration state.
optional RegistrationSyncRequestMessage registration_sync_request_message = 5;
// Request to change config from the server.
optional ConfigChangeMessage config_change_message = 6;
// Request for client information.
optional InfoRequestMessage info_request_message = 7;
// Asynchronous error information that the server sends to the client.
optional ErrorMessage error_message = 8;
}
// Message used to supply a new client token or invalidate an existing one.
message TokenControlMessage {
// If status is failure, new_token cannot be set.
optional bytes new_token = 1; // If missing, means destroy_token
}
// Status of a particular registration (could be sent spontaneously by the
// server or in response to a registration request).
message RegistrationStatus {
optional RegistrationP registration = 1;
optional StatusP status = 2;
}
// Registration status of several messages from the server to the client.
message RegistrationStatusMessage {
repeated RegistrationStatus registration_status = 1;
}
// Request from the server to get the registration info from the client for
// sync purposes.
message RegistrationSyncRequestMessage {
}
// A set of invalidations from the client to the server or vice-versa
message InvalidationMessage {
repeated InvalidationP invalidation = 1;
}
// A request from the server to the client for information such as
// performance counters, client os, etc
message InfoRequestMessage {
enum InfoType {
GET_PERFORMANCE_COUNTERS = 1;
}
repeated InfoType info_type = 1;
}
// A rate limit: a count of events and a window duration in which the events
// may occur.
message RateLimitP {
// The size of the window over which the rate limit applies.
optional int32 window_ms = 1;
// The number of events allowed within a given window.
optional int32 count = 2;
}
// Configuration parameters for the protocol handler in the Ticl.
message ProtocolHandlerConfigP {
// Batching delay - certain messages (e.g., registrations, invalidation acks)
// are sent to the server after this delay.
optional int32 batching_delay_ms = 1 [default = 500];
// Rate limits for sending messages. Only two levels allowed currently.
repeated RateLimitP rate_limit = 2;
}
// Configuration parameters for the Ticl.
message ClientConfigP {
optional Version version = 1;
// The delay after which a network message sent to the server is considered
// timed out.
optional int32 network_timeout_delay_ms = 2 [default = 60000];
// Retry delay for a persistent write if it fails
optional int32 write_retry_delay_ms = 3 [default = 10000];
// Delay for sending heartbeats to the server.
optional int32 heartbeat_interval_ms = 4 [default = 1200000];
// Delay after which performance counters are sent to the server.
optional int32 perf_counter_delay_ms = 5 [default = 21600000]; // 6 hours.
// The maximum exponential backoff factor used for network and persistence
/// timeouts.
optional int32 max_exponential_backoff_factor = 6 [default = 500];
// Smearing percent for randomizing delays.
optional int32 smear_percent = 7 [default = 20];
// Whether the client is transient, that is, does not write its session
// token to durable storage.
// TODO(xiaolan): (BUG 5627144) need to expose to the clients.
// For android the default is false. But for mtrx the default is true.
optional bool is_transient = 8 [default = false];
// Initial delay for a heartbeat after restarting from persistent state. We
// use this so that the application has a chance to respond to the
// reissueRegistrations call.
optional int32 initial_persistent_heartbeat_delay_ms = 9 [default = 2000];
// Configuration for the protocol client to control batching etc.
optional ProtocolHandlerConfigP protocol_handler_config = 10;
// Whether the channel supports delivery while the client is offline. If
// true, then the servers' use of the channel is such that the
// following holds: if any number of messages are sent to the client while
// the client is unreachable, then the channel will eventually deliver at
// least one message to the client such that, on receiving the message, the
// client will send a message to the server. E.g., the channel could deliver
// a single invalidation or a single registration sync request. C2DM is
// an example of a suitable channel.
//
// When this is true, the Ticl will record in persistent storage the last
// time it sent a message to the server. On persistent restart, it will not
// send a message to the server unless the last one was sent more than a
// heartbeat-interval ago. This is designed to support efficient Android
// clients, which will destroy and recreate the Ticl when transitioning
// between foreground and background states.
optional bool channel_supports_offline_delivery = 11 [default = false];
// If the client loses network connectivity, it will send a heartbeat after it
// comes online, unless it had already sent a message more recently than this
// threshold.
optional int32 offline_heartbeat_threshold_ms = 12 [default = 60000];
// Whether the client allows suppression. If true (the default), then
// both continuous and restarted invalidations result in an invalidate()
// upcall, which is appropriate for invalidation clients. If false,
// then restarted invalidations result in an invalidateUnknownVersion()
// upcall, which provides correct semantics for Trickles clients.
optional bool allow_suppression = 13 [default = true];
}
// A message asking the client to change its configuration parameters
message ConfigChangeMessage {
// On receipt of this value, do not send any new message to the server
// for the specified delay (this message needs to be accepted without
// any token check). A zero value is ignored by the client. So the lowest
// value for this field is 1. This concept exists to allow the server
// to tell the clients that they should not come back to the server
// for some period of time.
optional int64 next_message_delay_ms = 1;
}
// An error message that contains an enum for different types of failures with a
// textual description of the failure (as the need arises new error codes will
// be added to this message).
message ErrorMessage {
enum Code {
AUTH_FAILURE = 1; // Authorization or authentication failure.
UNKNOWN_FAILURE = 10000; // Some failure which is not described above.
};
optional Code code = 1;
// Textual description of the error
optional string description = 2;
}