diff --git a/src/security/tls_session.cpp b/src/security/tls_session.cpp
index 4a36762def5e70bcd6a396744946b32eda751517..5753dacb07b834c01e074e78e79617f6272949cd 100644
--- a/src/security/tls_session.cpp
+++ b/src/security/tls_session.cpp
@@ -941,10 +941,25 @@ TlsSession::handleDataPacket(std::vector<uint8_t>&& buf, uint64_t pkt_seq)
 void
 TlsSession::flushRxQueue()
 {
+    // RAII bool swap
+    class GuardedBoolSwap {
+    public:
+        explicit GuardedBoolSwap(bool& var) : var_ {var} { var_ = !var_; }
+        ~GuardedBoolSwap() { var_ = !var_; }
+    private:
+        bool& var_;
+    };
+
     std::unique_lock<std::mutex> lk {reorderBufMutex_};
     if (reorderBuffer_.empty())
         return;
 
+    // Prevent re-entrant access as the callbacks_.onRxData() is called in unprotected region
+    if (flushProcessing_)
+        return;
+
+    GuardedBoolSwap swap_flush_processing {flushProcessing_};
+
     auto item = std::begin(reorderBuffer_);
     auto next_offset = item->first;
     auto first_offset = next_offset;
diff --git a/src/security/tls_session.h b/src/security/tls_session.h
index de0457314879a8d491e2145acea0175efe05ecfa..c36a79bfa27cea421e7cc59889c86ccd4f69d2bd 100644
--- a/src/security/tls_session.h
+++ b/src/security/tls_session.h
@@ -219,6 +219,7 @@ private:
     std::list<std::vector<uint8_t>> rxQueue_ {};
 
     std::mutex reorderBufMutex_;
+    bool flushProcessing_ {false}; ///< protect against recursive call to flushRxQueue
     std::vector<uint8_t> rawPktBuf_; ///< gnutls incoming packet buffer
     uint64_t baseSeq_ {0}; ///< sequence number of first application data packet received
     uint64_t lastRxSeq_ {0}; ///< last received and valid packet sequence number