ftl_messaging_client.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. // Copyright 2019 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. #include "remoting/signaling/ftl_messaging_client.h"
  5. #include <utility>
  6. #include "base/callback.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/guid.h"
  9. #include "base/logging.h"
  10. #include "base/time/time.h"
  11. #include "net/traffic_annotation/network_traffic_annotation.h"
  12. #include "remoting/base/protobuf_http_client.h"
  13. #include "remoting/base/protobuf_http_request.h"
  14. #include "remoting/base/protobuf_http_request_config.h"
  15. #include "remoting/base/protobuf_http_status.h"
  16. #include "remoting/base/protobuf_http_stream_request.h"
  17. #include "remoting/signaling/ftl_message_reception_channel.h"
  18. #include "remoting/signaling/ftl_services_context.h"
  19. #include "remoting/signaling/registration_manager.h"
  20. #include "services/network/public/cpp/shared_url_loader_factory.h"
  21. namespace remoting {
  22. namespace {
  23. constexpr char kBatchAckMessagesPath[] = "/v1/message:batchAckMessages";
  24. constexpr char kReceiveMessagesPath[] = "/v1/messages:receive";
  25. constexpr char kSendMessagePath[] = "/v1/message:send";
  26. constexpr net::NetworkTrafficAnnotationTag kAckMessagesTrafficAnnotation =
  27. net::DefineNetworkTrafficAnnotation("ftl_messaging_client_ack_messages",
  28. R"(
  29. semantics {
  30. sender: "Chrome Remote Desktop"
  31. description:
  32. "Acknowledges the receipt of a signaling message from the Chrome "
  33. "Remote Desktop backend."
  34. trigger:
  35. "Initiating a Chrome Remote Desktop connection."
  36. data:
  37. "User's auth code and message ID for the message to be acknowledged."
  38. destination: GOOGLE_OWNED_SERVICE
  39. }
  40. policy {
  41. cookies_allowed: NO
  42. setting:
  43. "This request cannot be stopped in settings, but will not be sent "
  44. "if the user does not use Chrome Remote Desktop."
  45. policy_exception_justification:
  46. "Not implemented."
  47. })");
  48. constexpr net::NetworkTrafficAnnotationTag kReceiveMessagesTrafficAnnotation =
  49. net::DefineNetworkTrafficAnnotation("ftl_messaging_client_receive_messages",
  50. R"(
  51. semantics {
  52. sender: "Chrome Remote Desktop"
  53. description:
  54. "Retrieves signaling messages from the Chrome Remote Desktop peer "
  55. "(either a Chrome Remote Desktop host or client) via the Chrome Remote "
  56. "Desktop backend."
  57. trigger:
  58. "Initiating a Chrome Remote Desktop connection."
  59. data:
  60. "User's auth code and registration ID for retrieving messages."
  61. destination: GOOGLE_OWNED_SERVICE
  62. }
  63. policy {
  64. cookies_allowed: NO
  65. setting:
  66. "This request cannot be stopped in settings, but will not be sent "
  67. "if the user does not use Chrome Remote Desktop."
  68. policy_exception_justification:
  69. "Not implemented."
  70. })");
  71. constexpr net::NetworkTrafficAnnotationTag kSendMessageTrafficAnnotation =
  72. net::DefineNetworkTrafficAnnotation("ftl_messaging_client_send_messages",
  73. R"(
  74. semantics {
  75. sender: "Chrome Remote Desktop"
  76. description:
  77. "Sends signaling messages to the Chrome Remote Desktop peer (either a "
  78. "Chrome Remote Desktop host or client) via the Chrome Remote Desktop "
  79. "backend."
  80. trigger:
  81. "Initiating a Chrome Remote Desktop connection."
  82. data:
  83. "User's auth code and Chrome Remote Desktop P2P signaling messages. "
  84. "This includes session authentication data, SDP (Session Description "
  85. "Protocol) messages, and ICE (Interactive Connectivity Establishment) "
  86. "candidates. Details can be found at "
  87. "https://tools.ietf.org/html/rfc4566 and "
  88. "https://tools.ietf.org/html/rfc5245."
  89. destination: GOOGLE_OWNED_SERVICE
  90. }
  91. policy {
  92. cookies_allowed: NO
  93. setting:
  94. "This request cannot be stopped in settings, but will not be sent "
  95. "if the user does not use Chrome Remote Desktop."
  96. policy_exception_justification:
  97. "Not implemented."
  98. })");
  99. constexpr base::TimeDelta kInboxMessageTtl = base::Minutes(1);
  100. } // namespace
  101. FtlMessagingClient::FtlMessagingClient(
  102. OAuthTokenGetter* token_getter,
  103. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
  104. RegistrationManager* registration_manager,
  105. SignalingTracker* signaling_tracker)
  106. : FtlMessagingClient(
  107. std::make_unique<ProtobufHttpClient>(
  108. FtlServicesContext::GetServerEndpoint(),
  109. token_getter,
  110. url_loader_factory),
  111. registration_manager,
  112. std::make_unique<FtlMessageReceptionChannel>(signaling_tracker)) {}
  113. FtlMessagingClient::FtlMessagingClient(
  114. std::unique_ptr<ProtobufHttpClient> client,
  115. RegistrationManager* registration_manager,
  116. std::unique_ptr<MessageReceptionChannel> channel) {
  117. DCHECK(client);
  118. DCHECK(registration_manager);
  119. DCHECK(channel);
  120. client_ = std::move(client);
  121. registration_manager_ = registration_manager;
  122. reception_channel_ = std::move(channel);
  123. reception_channel_->Initialize(
  124. base::BindRepeating(&FtlMessagingClient::OpenReceiveMessagesStream,
  125. base::Unretained(this)),
  126. base::BindRepeating(&FtlMessagingClient::OnMessageReceived,
  127. base::Unretained(this)));
  128. }
  129. FtlMessagingClient::~FtlMessagingClient() = default;
  130. base::CallbackListSubscription FtlMessagingClient::RegisterMessageCallback(
  131. const MessageCallback& callback) {
  132. return callback_list_.Add(callback);
  133. }
  134. void FtlMessagingClient::SendMessage(
  135. const std::string& destination,
  136. const std::string& destination_registration_id,
  137. const ftl::ChromotingMessage& message,
  138. DoneCallback on_done) {
  139. auto request = std::make_unique<ftl::InboxSendRequest>();
  140. *request->mutable_header() = FtlServicesContext::CreateRequestHeader(
  141. registration_manager_->GetFtlAuthToken());
  142. request->set_time_to_live(kInboxMessageTtl.InMicroseconds());
  143. *request->mutable_dest_id() =
  144. FtlServicesContext::CreateIdFromString(destination);
  145. std::string serialized_message;
  146. bool succeeded = message.SerializeToString(&serialized_message);
  147. DCHECK(succeeded);
  148. request->mutable_message()->set_message(serialized_message);
  149. request->mutable_message()->set_message_id(base::GenerateGUID());
  150. request->mutable_message()->set_message_type(
  151. ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE);
  152. request->mutable_message()->set_message_class(
  153. ftl::InboxMessage_MessageClass_STATUS);
  154. if (!destination_registration_id.empty()) {
  155. request->add_dest_registration_ids(destination_registration_id);
  156. }
  157. ExecuteRequest(kSendMessageTrafficAnnotation, kSendMessagePath,
  158. std::move(request), &FtlMessagingClient::OnSendMessageResponse,
  159. std::move(on_done));
  160. }
  161. void FtlMessagingClient::StartReceivingMessages(base::OnceClosure on_ready,
  162. DoneCallback on_closed) {
  163. reception_channel_->StartReceivingMessages(std::move(on_ready),
  164. std::move(on_closed));
  165. }
  166. void FtlMessagingClient::StopReceivingMessages() {
  167. reception_channel_->StopReceivingMessages();
  168. }
  169. bool FtlMessagingClient::IsReceivingMessages() const {
  170. return reception_channel_->IsReceivingMessages();
  171. }
  172. template <typename CallbackFunctor>
  173. void FtlMessagingClient::ExecuteRequest(
  174. const net::NetworkTrafficAnnotationTag& tag,
  175. const std::string& path,
  176. std::unique_ptr<google::protobuf::MessageLite> request,
  177. CallbackFunctor callback_functor,
  178. DoneCallback on_done) {
  179. auto config = std::make_unique<ProtobufHttpRequestConfig>(tag);
  180. config->request_message = std::move(request);
  181. config->path = path;
  182. auto http_request = std::make_unique<ProtobufHttpRequest>(std::move(config));
  183. http_request->SetResponseCallback(base::BindOnce(
  184. callback_functor, base::Unretained(this), std::move(on_done)));
  185. client_->ExecuteRequest(std::move(http_request));
  186. }
  187. void FtlMessagingClient::OnSendMessageResponse(
  188. DoneCallback on_done,
  189. const ProtobufHttpStatus& status,
  190. std::unique_ptr<ftl::InboxSendResponse> response) {
  191. std::move(on_done).Run(status);
  192. }
  193. void FtlMessagingClient::BatchAckMessages(
  194. const ftl::BatchAckMessagesRequest& request,
  195. DoneCallback on_done) {
  196. // BatchAckMessages has a limit of 10 acks per call. Currently we ack one
  197. // message at a time, but check here to be safe.
  198. DCHECK_LE(request.message_ids_size(), 10);
  199. VLOG(1) << "Acking " << request.message_ids_size() << " messages";
  200. ExecuteRequest(kAckMessagesTrafficAnnotation, kBatchAckMessagesPath,
  201. std::make_unique<ftl::BatchAckMessagesRequest>(request),
  202. &FtlMessagingClient::OnBatchAckMessagesResponse,
  203. std::move(on_done));
  204. }
  205. void FtlMessagingClient::OnBatchAckMessagesResponse(
  206. DoneCallback on_done,
  207. const ProtobufHttpStatus& status,
  208. std::unique_ptr<ftl::BatchAckMessagesResponse> response) {
  209. // TODO(yuweih): Handle failure.
  210. std::move(on_done).Run(status);
  211. }
  212. std::unique_ptr<ScopedProtobufHttpRequest>
  213. FtlMessagingClient::OpenReceiveMessagesStream(
  214. base::OnceClosure on_channel_ready,
  215. const base::RepeatingCallback<
  216. void(std::unique_ptr<ftl::ReceiveMessagesResponse>)>& on_incoming_msg,
  217. base::OnceCallback<void(const ProtobufHttpStatus&)> on_channel_closed) {
  218. auto request = std::make_unique<ftl::ReceiveMessagesRequest>();
  219. *request->mutable_header() = FtlServicesContext::CreateRequestHeader(
  220. registration_manager_->GetFtlAuthToken());
  221. auto config = std::make_unique<ProtobufHttpRequestConfig>(
  222. kReceiveMessagesTrafficAnnotation);
  223. config->request_message = std::move(request);
  224. config->path = kReceiveMessagesPath;
  225. auto stream_request =
  226. std::make_unique<ProtobufHttpStreamRequest>(std::move(config));
  227. stream_request->SetStreamReadyCallback(std::move(on_channel_ready));
  228. stream_request->SetMessageCallback(on_incoming_msg);
  229. stream_request->SetStreamClosedCallback(std::move(on_channel_closed));
  230. auto request_holder = stream_request->CreateScopedRequest();
  231. client_->ExecuteRequest(std::move(stream_request));
  232. return request_holder;
  233. }
  234. void FtlMessagingClient::RunMessageCallbacks(const ftl::InboxMessage& message) {
  235. if (message_tracker_.IsIdTracked(message.message_id())) {
  236. LOG(WARNING) << "Found message with duplicated message ID: "
  237. << message.message_id();
  238. return;
  239. }
  240. message_tracker_.TrackId(message.message_id());
  241. if (message.sender_id().type() != ftl::IdType_Type_SYSTEM &&
  242. message.sender_registration_id().empty()) {
  243. LOG(WARNING) << "Ignored peer message with no sender registration ID.";
  244. return;
  245. }
  246. if (message.message_type() !=
  247. ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE) {
  248. LOG(WARNING) << "Received message with unknown type: "
  249. << message.message_type()
  250. << ", sender: " << message.sender_id().id();
  251. return;
  252. }
  253. ftl::ChromotingMessage chromoting_message;
  254. chromoting_message.ParseFromString(message.message());
  255. callback_list_.Notify(message.sender_id(), message.sender_registration_id(),
  256. chromoting_message);
  257. }
  258. void FtlMessagingClient::OnMessageReceived(const ftl::InboxMessage& message) {
  259. RunMessageCallbacks(message);
  260. ftl::BatchAckMessagesRequest request;
  261. *request.mutable_header() = FtlServicesContext::CreateRequestHeader(
  262. registration_manager_->GetFtlAuthToken());
  263. request.add_message_ids(message.message_id());
  264. BatchAckMessages(request, base::DoNothing());
  265. }
  266. } // namespace remoting