// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// MCS protocol for communication between Chrome client and Mobile Connection
// Server .

syntax = "proto2";

option optimize_for = LITE_RUNTIME;

package mcs_proto;

/*
   Common fields/comments:

    stream_id: no longer sent by server, each side keeps a counter
    last_stream_id_received: sent only if a packet was received since last time
    a last_stream was sent
    status: new bitmask including the 'idle' as bit 0.

 */

/**
  TAG: 0
  */
message HeartbeatPing {
  optional int32 stream_id = 1;
  optional int32 last_stream_id_received = 2;
  optional int64 status = 3;
}

/**
  TAG: 1
  */
message HeartbeatAck {
  optional int32 stream_id = 1;
  optional int32 last_stream_id_received = 2;
  optional int64 status = 3;
}

message ErrorInfo {
  required int32 code = 1;
  optional string message = 2;
  optional string type = 3;
  optional  Extension extension = 4;
}

// MobileSettings class.
// "u:f", "u:b", "u:s" - multi user devices reporting foreground, background
// and stopped users.
// hbping: heatbeat ping interval
// rmq2v: include explicit stream IDs

message Setting {
  required string name = 1;
  required string value = 2;
}

message HeartbeatStat {
  required string ip = 1;
  required bool timeout = 2;
  required int32 interval_ms = 3;
}

message HeartbeatConfig {
  optional bool upload_stat = 1;
  optional string ip = 2;
  optional int32 interval_ms = 3;
}

// ClientEvents are used to inform the server of failed and successful
// connections.
message ClientEvent {
  enum Type {
    UNKNOWN = 0;
    // Count of discarded events if the buffer filled up and was trimmed.
    DISCARDED_EVENTS = 1;
    // Failed connection event: the connection failed to be established or we
    // had a login error.
    FAILED_CONNECTION = 2;
    // Successful connection event: information about the last successful
    // connection, including the time at which it was established.
    SUCCESSFUL_CONNECTION = 3;
  }

  // Common fields [1-99]
  optional Type type = 1;

  // Fields for DISCARDED_EVENTS messages [100-199]
  optional uint32 number_discarded_events = 100;

  // Fields for FAILED_CONNECTION and SUCCESSFUL_CONNECTION messages [200-299]
  // Network type is a value in net::NetworkChangeNotifier::ConnectionType.
  optional int32 network_type = 200;
  // Reserved for network_port.
  reserved 201;
  optional uint64 time_connection_started_ms = 202;
  optional uint64 time_connection_ended_ms = 203;
  // Error code should be a net::Error value.
  optional int32 error_code = 204;

  // Fields for SUCCESSFUL_CONNECTION messages [300-399]
  optional uint64 time_connection_established_ms = 300;
}

/**
  TAG: 2
  */
message LoginRequest {
  enum AuthService {
    ANDROID_ID = 2;
  }
  required string id = 1; // Must be present ( proto required ), may be empty
                          // string.
  // mcs.android.com.
  required string domain = 2;
  // Decimal android ID
  required string user = 3;

  required string resource = 4;

  // Secret
  required string auth_token = 5;

  // Format is: android-HEX_DEVICE_ID
  // The user is the decimal value.
  optional string device_id = 6;

  // RMQ1 - no longer used
  optional int64 last_rmq_id = 7;

  repeated Setting setting = 8;
  //optional int32 compress = 9;
  repeated string received_persistent_id = 10;

  // Replaced by "rmq2v" setting
  // optional bool include_stream_ids = 11;

  optional bool adaptive_heartbeat = 12;
  optional HeartbeatStat heartbeat_stat = 13;
  // Must be true.
  optional bool use_rmq2 = 14;
  optional int64 account_id = 15;

  // ANDROID_ID = 2
  optional AuthService auth_service = 16;

  optional int32 network_type = 17;
  optional int64 status = 18;

  // 19, 20, and 21 are not currently populated by Chrome.
  reserved 19, 20, 21;

  // Events recorded on the client after the last successful connection.
  repeated ClientEvent client_event = 22;
}

/**
  * TAG: 3
  */
message LoginResponse {
  required string id = 1;
  // Not used.
  optional string jid = 2;
  // Null if login was ok.
  optional ErrorInfo error = 3;
  repeated Setting setting = 4;
  optional int32 stream_id = 5;
  // Should be "1"
  optional int32 last_stream_id_received = 6;
  optional HeartbeatConfig heartbeat_config = 7;
  // used by the client to synchronize with the server timestamp.
  optional int64 server_timestamp = 8;
}

message StreamErrorStanza {
  required string type = 1;
  optional string text = 2;
}

/**
  * TAG: 4
  */
message Close {
}

message Extension {
  // 12: SelectiveAck
  // 13: StreamAck
  required int32 id = 1;
  required bytes data = 2;
}

/**
  * TAG: 7
  * IqRequest must contain a single extension.  IqResponse may contain 0 or 1
  * extensions.
  */
message IqStanza {
  enum IqType {
    GET = 0;
    SET = 1;
    RESULT = 2;
    IQ_ERROR = 3;
  }

  optional int64 rmq_id = 1;
  required IqType type = 2;
  required string id = 3;
  optional string from = 4;
  optional string to = 5;
  optional ErrorInfo error = 6;

  // Only field used in the 38+ protocol (besides common last_stream_id_received, status, rmq_id)
  optional Extension extension = 7;

  optional string persistent_id = 8;
  optional int32 stream_id = 9;
  optional int32 last_stream_id_received = 10;
  optional int64 account_id = 11;
  optional int64 status = 12;
}

message AppData {
  required string key = 1;
  required string value = 2;
}

/**
 * TAG: 8
 */
message DataMessageStanza {
  // Not used.
  // optional int64 rmq_id = 1;

  // This is the message ID, set by client, DMP.9 (message_id)
  optional string id = 2;

  // Project ID of the sender, DMP.1
  required string from = 3;

  // Part of DMRequest - also the key in DataMessageProto.
  optional string to = 4;

  // Package name. DMP.2
  required string category = 5;

  // The collapsed key, DMP.3
  optional string token = 6;

  // User data + GOOGLE. prefixed special entries, DMP.4
  repeated AppData app_data = 7;

  // Not used.
  optional bool from_trusted_server = 8;

  // Part of the ACK protocol, returned in DataMessageResponse on server side.
  // It's part of the key of DMP.
  optional string persistent_id = 9;

  // In-stream ack. Increments on each message sent - a bit redundant
  // Not used in DMP/DMR.
  optional int32 stream_id = 10;
  optional int32 last_stream_id_received = 11;

  // Not used.
  // optional string permission = 12;

  // Sent by the device shortly after registration.
  optional string reg_id = 13;

  // Not used.
  // optional string pkg_signature = 14;
  // Not used.
  // optional string client_id = 15;

  // serial number of the target user, DMP.8
  // It is the 'serial number' according to user manager.
  optional int64 device_user_id = 16;

  // Time to live, in seconds.
  optional int32 ttl = 17;
  // Timestamp ( according to client ) when message was sent by app, in seconds
  optional int64 sent = 18;

  // How long has the message been queued before the flush, in seconds.
  // This is needed to account for the time difference between server and
  // client: server should adjust 'sent' based on its 'receive' time.
  optional int32 queued = 19;

  optional int64 status = 20;

  // Optional field containing the binary payload of the message.
  optional bytes raw_data = 21;

  // Not used.
  // The maximum delay of the message, in seconds.
  // optional int32 max_delay = 22;

  // Not used.
  // How long the message was delayed before it was sent, in seconds.
  // optional int32 actual_delay = 23;

  // If set the server requests immediate ack. Used for important messages and
  // for testing.
  optional bool immediate_ack = 24;

  // Not used.
  // Enables message receipts from MCS/GCM back to CCS clients
  // optional bool delivery_receipt_requested = 25;
}

/**
  Included in IQ with ID 13, sent from client or server after 10 unconfirmed
  messages.
 */
message StreamAck {
  // No last_streamid_received required.  This is included within an IqStanza,
  // which includes the last_stream_id_received.
}

/**
  Included in IQ sent after LoginResponse from server with ID 12.
*/
message SelectiveAck {
  repeated string id = 1;
}
