buffet: Add correct handling of XMPP IQ stanzas
Implemented a more intelligent handling of IQ requests and responses.
Each time an IQ request is sent, a new unique request ID is generated
and then a response with the same ID is expected. If no reponse is
received within a timeout interval (of 30 seconds) a timeout callback
is called allowing the caller to handle this event correctly.
Changed the XMPP connection handshake implementation which used some
of IQ stanza exchange with the server to use the new IqStanzaHandler
class.
BUG=brillo:1138
TEST=`FEATURES=test emerge-link buffet`
Change-Id: I9534169466159d7531e5f01a25a0583ca6b341c3
Reviewed-on: https://chromium-review.googlesource.com/274446
Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/notification/xmpp_iq_stanza_handler.h b/buffet/notification/xmpp_iq_stanza_handler.h
new file mode 100644
index 0000000..0eb0900
--- /dev/null
+++ b/buffet/notification/xmpp_iq_stanza_handler.h
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BUFFET_NOTIFICATION_XMPP_IQ_STANZA_HANDLER_H_
+#define BUFFET_NOTIFICATION_XMPP_IQ_STANZA_HANDLER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <base/callback_forward.h>
+#include <base/macros.h>
+#include <base/memory/weak_ptr.h>
+#include <base/single_thread_task_runner.h>
+
+#include "buffet/notification/xmpp_stream_parser.h"
+
+namespace buffet {
+
+class XmppChannelInterface;
+
+class IqStanzaHandler {
+ public:
+ using ResponseCallback =
+ base::Callback<void(std::unique_ptr<XmlNode>)>;
+ using TimeoutCallback = base::Closure;
+
+ IqStanzaHandler(
+ XmppChannelInterface* xmpp_channel,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+
+ // Sends <iq> request to the server.
+ // |type| is the IQ stanza type, one of "get", "set", "query".
+ // |to| is the target of the message. If empty string, 'to' is omitted.
+ // |body| the XML snipped to include between <iq>...</iq>
+ // |response_callback| is called with result or error XML stanza received
+ // from the server in response to the request sent.
+ // |timeout_callback| is called when the response to the request hasn't been
+ // received within the time allotted.
+ void SendRequest(const std::string& type,
+ const std::string& from,
+ const std::string& to,
+ const std::string& body,
+ const ResponseCallback& response_callback,
+ const TimeoutCallback& timeout_callback);
+
+ // Processes an <iq> stanza is received from the server. This will match the
+ // stanza's 'id' attribute with pending request ID and if found, will
+ // call the |response_callback|, or if the request is not found, an error
+ // stanza fill be sent back to the server.
+ // Returns false if some unexpected condition occurred and the stream should
+ // be restarted.
+ bool HandleIqStanza(std::unique_ptr<XmlNode> stanza);
+
+ private:
+ using RequestId = int;
+ void OnTimeOut(RequestId id, const TimeoutCallback& timeout_callback);
+
+ XmppChannelInterface* xmpp_channel_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ std::map<RequestId, ResponseCallback> requests_;
+ RequestId last_request_id_{0};
+
+ base::WeakPtrFactory<IqStanzaHandler> weak_ptr_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(IqStanzaHandler);
+};
+
+} // namespace buffet
+
+#endif // BUFFET_NOTIFICATION_XMPP_IQ_STANZA_HANDLER_H_
+