/* * 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"; package com.google.protos.ipc.invalidation; option optimize_for = LITE_RUNTIME; option java_outer_classname = "ClientProtocol"; // 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. This field is logically // required and is always set by current code. The default is true because // old Android invalidation clients strip this field when acking // invalidations due to ProtoLite limitations; true is the correct default // because invalidation clients logically ack all current versions and // because old persisted invalidations are all restarted. optional bool is_trickle_restart = 6 [default = true]; // 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. TODO: Determine and specify this // more precisely. 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; } // If ServerToClientMessage is modified, you need to change the type // TestServerToClientMessageWithExtraFields in the same way to match. 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: need to expose to the clients. 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; }