mcs_util.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "google_apis/gcm/base/mcs_util.h"
6
7#include "base/format_macros.h"
8#include "base/logging.h"
9#include "base/strings/string_number_conversions.h"
10#include "base/strings/stringprintf.h"
11
12namespace gcm {
13
14namespace {
15
16// Type names corresponding to MCSProtoTags. Useful for identifying what type
17// of MCS protobuf is contained within a google::protobuf::MessageLite object.
18// WARNING: must match the order in MCSProtoTag.
19const char* kProtoNames[] = {
20  "mcs_proto.HeartbeatPing",
21  "mcs_proto.HeartbeatAck",
22  "mcs_proto.LoginRequest",
23  "mcs_proto.LoginResponse",
24  "mcs_proto.Close",
25  "mcs_proto.MessageStanza",
26  "mcs_proto.PresenceStanza",
27  "mcs_proto.IqStanza",
28  "mcs_proto.DataMessageStanza",
29  "mcs_proto.BatchPresenceStanza",
30  "mcs_proto.StreamErrorStanza",
31  "mcs_proto.HttpRequest",
32  "mcs_proto.HttpResponse",
33  "mcs_proto.BindAccountRequest",
34  "mcs_proto.BindAccountResponse",
35  "mcs_proto.TalkMetadata"
36};
37COMPILE_ASSERT(arraysize(kProtoNames) == kNumProtoTypes,
38               ProtoNamesMustIncludeAllTags);
39
40// TODO(zea): replace these with proper values.
41const char kLoginId[] = "login-1";
42const char kLoginDomain[] = "mcs.android.com";
43const char kLoginDeviceIdPrefix[] = "android-";
44const char kLoginSettingName[] = "new_vc";
45const char kLoginSettingValue[] = "1";
46
47}  // namespace
48
49scoped_ptr<mcs_proto::LoginRequest> BuildLoginRequest(
50    uint64 auth_id,
51    uint64 auth_token) {
52  // Create a hex encoded auth id for the device id field.
53  std::string auth_id_hex;
54  auth_id_hex = base::StringPrintf("%" PRIx64, auth_id);
55
56  std::string auth_id_str = base::Uint64ToString(auth_id);
57  std::string auth_token_str = base::Uint64ToString(auth_token);
58
59  scoped_ptr<mcs_proto::LoginRequest> login_request(
60      new mcs_proto::LoginRequest());
61
62  // TODO(zea): set better values.
63  login_request->set_account_id(1000000);
64  login_request->set_adaptive_heartbeat(false);
65  login_request->set_auth_service(mcs_proto::LoginRequest::ANDROID_ID);
66  login_request->set_auth_token(auth_token_str);
67  login_request->set_id(kLoginId);
68  login_request->set_domain(kLoginDomain);
69  login_request->set_device_id(kLoginDeviceIdPrefix + auth_id_hex);
70  login_request->set_network_type(1);
71  login_request->set_resource(auth_id_str);
72  login_request->set_user(auth_id_str);
73  login_request->set_use_rmq2(true);
74
75  login_request->add_setting();
76  login_request->mutable_setting(0)->set_name(kLoginSettingName);
77  login_request->mutable_setting(0)->set_value(kLoginSettingValue);
78  return login_request.Pass();
79}
80
81scoped_ptr<mcs_proto::IqStanza> BuildStreamAck() {
82  scoped_ptr<mcs_proto::IqStanza> stream_ack_iq(new mcs_proto::IqStanza());
83  stream_ack_iq->set_type(mcs_proto::IqStanza::SET);
84  stream_ack_iq->set_id("");
85  stream_ack_iq->mutable_extension()->set_id(kStreamAck);
86  stream_ack_iq->mutable_extension()->set_data("");
87  return stream_ack_iq.Pass();
88}
89
90// Utility method to build a google::protobuf::MessageLite object from a MCS
91// tag.
92scoped_ptr<google::protobuf::MessageLite> BuildProtobufFromTag(uint8 tag) {
93  switch(tag) {
94    case kHeartbeatPingTag:
95      return scoped_ptr<google::protobuf::MessageLite>(
96          new mcs_proto::HeartbeatPing());
97    case kHeartbeatAckTag:
98      return scoped_ptr<google::protobuf::MessageLite>(
99          new mcs_proto::HeartbeatAck());
100    case kLoginRequestTag:
101      return scoped_ptr<google::protobuf::MessageLite>(
102          new mcs_proto::LoginRequest());
103    case kLoginResponseTag:
104      return scoped_ptr<google::protobuf::MessageLite>(
105          new mcs_proto::LoginResponse());
106    case kCloseTag:
107      return scoped_ptr<google::protobuf::MessageLite>(
108          new mcs_proto::Close());
109    case kIqStanzaTag:
110      return scoped_ptr<google::protobuf::MessageLite>(
111          new mcs_proto::IqStanza());
112    case kDataMessageStanzaTag:
113      return scoped_ptr<google::protobuf::MessageLite>(
114          new mcs_proto::DataMessageStanza());
115    case kStreamErrorStanzaTag:
116      return scoped_ptr<google::protobuf::MessageLite>(
117          new mcs_proto::StreamErrorStanza());
118    default:
119      return scoped_ptr<google::protobuf::MessageLite>();
120  }
121}
122
123// Utility method to extract a MCS tag from a google::protobuf::MessageLite
124// object.
125int GetMCSProtoTag(const google::protobuf::MessageLite& message) {
126  const std::string& type_name = message.GetTypeName();
127  if (type_name == kProtoNames[kHeartbeatPingTag]) {
128    return kHeartbeatPingTag;
129  } else if (type_name == kProtoNames[kHeartbeatAckTag]) {
130    return kHeartbeatAckTag;
131  } else if (type_name == kProtoNames[kLoginRequestTag]) {
132    return kLoginRequestTag;
133  } else if (type_name == kProtoNames[kLoginResponseTag]) {
134    return kLoginResponseTag;
135  } else if (type_name == kProtoNames[kCloseTag]) {
136    return kCloseTag;
137  } else if (type_name == kProtoNames[kIqStanzaTag]) {
138    return kIqStanzaTag;
139  } else if (type_name == kProtoNames[kDataMessageStanzaTag]) {
140    return kDataMessageStanzaTag;
141  } else if (type_name == kProtoNames[kStreamErrorStanzaTag]) {
142    return kStreamErrorStanzaTag;
143  }
144  return -1;
145}
146
147std::string GetPersistentId(const google::protobuf::MessageLite& protobuf) {
148  if (protobuf.GetTypeName() == kProtoNames[kIqStanzaTag]) {
149    return reinterpret_cast<const mcs_proto::IqStanza*>(&protobuf)->
150        persistent_id();
151  } else if (protobuf.GetTypeName() == kProtoNames[kDataMessageStanzaTag]) {
152    return reinterpret_cast<const mcs_proto::DataMessageStanza*>(&protobuf)->
153        persistent_id();
154  }
155  // Not all message types have persistent ids. Just return empty string;
156  return "";
157}
158
159void SetPersistentId(const std::string& persistent_id,
160                     google::protobuf::MessageLite* protobuf) {
161  if (protobuf->GetTypeName() == kProtoNames[kIqStanzaTag]) {
162    reinterpret_cast<mcs_proto::IqStanza*>(protobuf)->
163        set_persistent_id(persistent_id);
164    return;
165  } else if (protobuf->GetTypeName() == kProtoNames[kDataMessageStanzaTag]) {
166    reinterpret_cast<mcs_proto::DataMessageStanza*>(protobuf)->
167        set_persistent_id(persistent_id);
168    return;
169  }
170  NOTREACHED();
171}
172
173uint32 GetLastStreamIdReceived(const google::protobuf::MessageLite& protobuf) {
174  if (protobuf.GetTypeName() == kProtoNames[kIqStanzaTag]) {
175    return reinterpret_cast<const mcs_proto::IqStanza*>(&protobuf)->
176        last_stream_id_received();
177  } else if (protobuf.GetTypeName() == kProtoNames[kDataMessageStanzaTag]) {
178    return reinterpret_cast<const mcs_proto::DataMessageStanza*>(&protobuf)->
179        last_stream_id_received();
180  } else if (protobuf.GetTypeName() == kProtoNames[kHeartbeatPingTag]) {
181    return reinterpret_cast<const mcs_proto::HeartbeatPing*>(&protobuf)->
182        last_stream_id_received();
183  } else if (protobuf.GetTypeName() == kProtoNames[kHeartbeatAckTag]) {
184    return reinterpret_cast<const mcs_proto::HeartbeatAck*>(&protobuf)->
185        last_stream_id_received();
186  } else if (protobuf.GetTypeName() == kProtoNames[kLoginResponseTag]) {
187    return reinterpret_cast<const mcs_proto::LoginResponse*>(&protobuf)->
188        last_stream_id_received();
189  }
190  // Not all message types have last stream ids. Just return 0.
191  return 0;
192}
193
194void SetLastStreamIdReceived(uint32 val,
195                             google::protobuf::MessageLite* protobuf) {
196  if (protobuf->GetTypeName() == kProtoNames[kIqStanzaTag]) {
197    reinterpret_cast<mcs_proto::IqStanza*>(protobuf)->
198        set_last_stream_id_received(val);
199     return;
200  } else if (protobuf->GetTypeName() == kProtoNames[kHeartbeatPingTag]) {
201    reinterpret_cast<mcs_proto::HeartbeatPing*>(protobuf)->
202        set_last_stream_id_received(val);
203     return;
204  } else if (protobuf->GetTypeName() == kProtoNames[kHeartbeatAckTag]) {
205    reinterpret_cast<mcs_proto::HeartbeatAck*>(protobuf)->
206        set_last_stream_id_received(val);
207     return;
208  } else if (protobuf->GetTypeName() == kProtoNames[kDataMessageStanzaTag]) {
209    reinterpret_cast<mcs_proto::DataMessageStanza*>(protobuf)->
210        set_last_stream_id_received(val);
211     return;
212  } else if (protobuf->GetTypeName() == kProtoNames[kLoginResponseTag]) {
213    reinterpret_cast<mcs_proto::LoginResponse*>(protobuf)->
214        set_last_stream_id_received(val);
215     return;
216  }
217  NOTREACHED();
218}
219
220}  // namespace gcm
221