From d62b9cbe2699d92ed7c7bc5cc3fe1f8e562f3c5a Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Thu, 2 Nov 2017 17:11:41 +0900 Subject: [PATCH] FirebaseArduino: allow mixing stream and non-stream commands With this change non-streaming operation will stop the stream and reuse the underlying http client. Call FirebaseArduino::stream again in order to reuse the stream. Fixes: #48 --- src/Firebase.cpp | 17 ++++++++++++++++- src/FirebaseArduino.cpp | 3 +++ src/FirebaseArduino.h | 3 --- src/FirebaseHttpClient.h | 11 +++++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Firebase.cpp b/src/Firebase.cpp index b3d72d32..d00787d1 100644 --- a/src/Firebase.cpp +++ b/src/Firebase.cpp @@ -92,6 +92,15 @@ FirebaseCall::FirebaseCall(const std::string& host, const std::string& auth, const char* method, const std::string& path, const std::string& data, FirebaseHttpClient* http) : http_(http) { std::string path_with_auth = makeFirebaseURL(path, auth); + if ((method == "STREAM") && (path == http->getStreamingPath())){ + // already streaming requested path. + return; + } + if (http_->isStreaming()) { + // closing streaming connection. + http_->setReuseConnection(false); + http_->end(); + } http_->setReuseConnection(true); http_->begin(host, path_with_auth); @@ -130,11 +139,14 @@ FirebaseCall::FirebaseCall(const std::string& host, const std::string& auth, // if not streaming. if (!followRedirect) { response_ = http_->getString(); + http_->setStreaming(""); + } else { + http_->setStreaming(path); } } FirebaseCall::~FirebaseCall() { - if (http_) { + if (http_ && !http_->isStreaming()) { http_->end(); } } @@ -189,6 +201,9 @@ FirebaseStream::FirebaseStream(const std::string& host, const std::string& auth, } bool FirebaseStream::available() { + if (http_->getStreamPtr() == nullptr) { + return false; + } return http_->getStreamPtr()->available(); } diff --git a/src/FirebaseArduino.cpp b/src/FirebaseArduino.cpp index bdf5105c..44dc056f 100644 --- a/src/FirebaseArduino.cpp +++ b/src/FirebaseArduino.cpp @@ -131,6 +131,9 @@ void FirebaseArduino::stream(const String& path) { } bool FirebaseArduino::available() { + if (http_->getStreamPtr() == nullptr) { + return false; + } return http_->getStreamPtr()->available(); } diff --git a/src/FirebaseArduino.h b/src/FirebaseArduino.h index a69f4e16..a0bcca27 100644 --- a/src/FirebaseArduino.h +++ b/src/FirebaseArduino.h @@ -189,9 +189,6 @@ class FirebaseArduino { * You should check success() after calling. * This changes the state of this object. Once this is called you may start * monitoring available() and calling readEvent() to get new events. - * WARNING: Currently you cannot make another call while the stream is - * running, otherwise you will crash due to memory issues. See: - * https://github.com/googlesamples/firebase-arduino/issues/48 * \param path The path inside of your db to the node you wish to monitor. */ void stream(const String& path); diff --git a/src/FirebaseHttpClient.h b/src/FirebaseHttpClient.h index 055699c7..1752ba2f 100644 --- a/src/FirebaseHttpClient.h +++ b/src/FirebaseHttpClient.h @@ -33,7 +33,18 @@ class FirebaseHttpClient { virtual std::string errorToString(int error_code) = 0; + bool isStreaming() const { + return _streaming != ""; + } + std::string getStreamingPath() const { + return _streaming; + } + void setStreaming(const std::string& path) { + _streaming = path; + } protected: + std::string _streaming = ""; + static const uint16_t kFirebasePort = 443; };