LCOV - code coverage report
Current view: top level - transport - Session.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 51 60 85.0 %
Date: 2024-02-15 08:20:41 Functions: 26 30 86.7 %

          Line data    Source code
       1             : /*
       2             :  *    Copyright (c) 2021 Project CHIP Authors
       3             :  *
       4             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       5             :  *    you may not use this file except in compliance with the License.
       6             :  *    You may obtain a copy of the License at
       7             :  *
       8             :  *        http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  *    Unless required by applicable law or agreed to in writing, software
      11             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      12             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  *    See the License for the specific language governing permissions and
      14             :  *    limitations under the License.
      15             :  */
      16             : 
      17             : #pragma once
      18             : 
      19             : #include <access/SubjectDescriptor.h>
      20             : #include <credentials/FabricTable.h>
      21             : #include <lib/core/CHIPConfig.h>
      22             : #include <lib/core/Optional.h>
      23             : #include <lib/core/PeerId.h>
      24             : #include <lib/core/ScopedNodeId.h>
      25             : #include <lib/support/IntrusiveList.h>
      26             : #include <lib/support/ReferenceCountedHandle.h>
      27             : #include <messaging/ReliableMessageProtocolConfig.h>
      28             : #include <messaging/SessionParameters.h>
      29             : #include <platform/LockTracker.h>
      30             : #include <transport/SessionDelegate.h>
      31             : 
      32             : namespace chip {
      33             : namespace Transport {
      34             : class Session;
      35             : } // namespace Transport
      36             : 
      37             : /** @brief
      38             :  *    Non-copyable session reference. All SessionHandles are created within SessionManager. It is not allowed to store SessionHandle
      39             :  *    anywhere except for function arguments and return values.
      40             :  *
      41             :  *    SessionHandle is reference counted such that it is never dangling, but there can be a gray period when the session is marked
      42             :  *    as pending removal but not actually removed yet. During this period, the handle is functional, but the underlying session
      43             :  *    won't be able to be grabbed by any SessionHolder. SessionHandle->IsActiveSession can be used to check if the session is
      44             :  *    active.
      45             :  */
      46             : class SessionHandle
      47             : {
      48             : public:
      49         459 :     SessionHandle(Transport::Session & session) : mSession(session) {}
      50          27 :     ~SessionHandle() {}
      51             : 
      52             :     SessionHandle(const SessionHandle &)           = delete;
      53             :     SessionHandle operator=(const SessionHandle &) = delete;
      54       33442 :     SessionHandle(SessionHandle &&)                = default;
      55             :     SessionHandle & operator=(SessionHandle &&)    = delete;
      56             : 
      57             :     bool operator==(const SessionHandle & that) const { return &mSession.Get() == &that.mSession.Get(); }
      58             : 
      59      114763 :     Transport::Session * operator->() const { return mSession.operator->(); }
      60             : 
      61             : private:
      62             :     friend class SessionHolder;
      63             :     ReferenceCountedHandle<Transport::Session> mSession;
      64             : };
      65             : 
      66             : /** @brief
      67             :  *    Managed session reference. The object is used to store a session, the stored session will be automatically
      68             :  *    released when the underlying session is released. One must verify it is available before use. The object can be
      69             :  *    created using SessionHandle.Grab()
      70             :  */
      71             : class SessionHolder : public IntrusiveListNodeBase<>
      72             : {
      73             : public:
      74           3 :     SessionHolder() {}
      75           0 :     SessionHolder(const SessionHandle & handle) { Grab(handle); }
      76             :     virtual ~SessionHolder();
      77             : 
      78             :     SessionHolder(const SessionHolder &);
      79             :     SessionHolder(SessionHolder && that);
      80             :     SessionHolder & operator=(const SessionHolder &);
      81             :     SessionHolder & operator=(SessionHolder && that);
      82             : 
      83        1319 :     virtual void SessionReleased() { Release(); }
      84           0 :     virtual void ShiftToSession(const SessionHandle & session)
      85             :     {
      86           0 :         Release();
      87           0 :         Grab(session);
      88           0 :     }
      89             : 
      90       11855 :     bool Contains(const SessionHandle & session) const
      91             :     {
      92       11855 :         return mSession.HasValue() && &mSession.Value().Get() == &session.mSession.Get();
      93             :     }
      94             : 
      95             :     bool GrabPairingSession(const SessionHandle & session); // Should be only used inside CASE/PASE pairing.
      96             :     bool Grab(const SessionHandle & session);
      97             :     void Release();
      98             : 
      99       93049 :     explicit operator bool() const { return mSession.HasValue(); }
     100       31779 :     Optional<SessionHandle> Get() const
     101             :     {
     102             :         //
     103             :         // We cannot return mSession directly even if Optional<SessionHandle> is internally composed of the same bits,
     104             :         // since they are not actually equivalent type-wise, and SessionHandle does not permit copy-construction.
     105             :         //
     106             :         // So, construct a new Optional<SessionHandle> from the underlying Transport::Session reference.
     107             :         //
     108       63558 :         return mSession.HasValue() ? chip::MakeOptional<SessionHandle>(mSession.Value().Get())
     109       63558 :                                    : chip::Optional<SessionHandle>::Missing();
     110             :     }
     111             : 
     112       64238 :     Transport::Session * operator->() const { return &mSession.Value().Get(); }
     113             : 
     114             :     // There is not delegate, nothing to do here
     115          11 :     virtual void DispatchSessionEvent(SessionDelegate::Event event) {}
     116             : 
     117             : protected:
     118             :     // Helper for use by the Grab methods.
     119             :     void GrabUnchecked(const SessionHandle & session);
     120             : 
     121             :     Optional<ReferenceCountedHandle<Transport::Session>> mSession;
     122             : };
     123             : 
     124             : /// @brief Extends SessionHolder to allow propagate SessionDelegate::* events to a given destination
     125             : class SessionHolderWithDelegate : public SessionHolder
     126             : {
     127             : public:
     128        3231 :     SessionHolderWithDelegate(SessionDelegate & delegate) : mDelegate(delegate) {}
     129             :     SessionHolderWithDelegate(const SessionHandle & handle, SessionDelegate & delegate) : SessionHolder(handle), mDelegate(delegate)
     130             :     {}
     131       85750 :     operator bool() const { return SessionHolder::operator bool(); }
     132             : 
     133          43 :     void SessionReleased() override
     134             :     {
     135          43 :         Release();
     136             : 
     137             :         // Note, the session is already cleared during mDelegate.OnSessionReleased
     138          43 :         mDelegate.OnSessionReleased();
     139          43 :     }
     140             : 
     141           0 :     void ShiftToSession(const SessionHandle & session) override
     142             :     {
     143           0 :         if (mDelegate.GetNewSessionHandlingPolicy() == SessionDelegate::NewSessionHandlingPolicy::kShiftToNewSession)
     144           0 :             SessionHolder::ShiftToSession(session);
     145           0 :     }
     146             : 
     147           8 :     void DispatchSessionEvent(SessionDelegate::Event event) override { (mDelegate.*event)(); }
     148             : 
     149             : private:
     150             :     SessionDelegate & mDelegate;
     151             : };
     152             : 
     153             : namespace Transport {
     154             : 
     155             : class SecureSession;
     156             : class UnauthenticatedSession;
     157             : class IncomingGroupSession;
     158             : class OutgoingGroupSession;
     159             : 
     160             : class Session
     161             : {
     162             : public:
     163      133776 :     virtual ~Session() {}
     164             : 
     165             :     enum class SessionType : uint8_t
     166             :     {
     167             :         kUndefined       = 0,
     168             :         kUnauthenticated = 1,
     169             :         kSecure          = 2,
     170             :         kGroupIncoming   = 3,
     171             :         kGroupOutgoing   = 4,
     172             :     };
     173             : 
     174             :     virtual SessionType GetSessionType() const = 0;
     175             : 
     176        8129 :     void AddHolder(SessionHolder & holder)
     177             :     {
     178        8129 :         assertChipStackLockedByCurrentThread();
     179        8129 :         VerifyOrDie(!holder.IsInList());
     180        8129 :         mHolders.PushBack(&holder);
     181        8129 :     }
     182             : 
     183        8129 :     void RemoveHolder(SessionHolder & holder)
     184             :     {
     185        8129 :         assertChipStackLockedByCurrentThread();
     186        8129 :         VerifyOrDie(mHolders.Contains(&holder));
     187        8129 :         mHolders.Remove(&holder);
     188        8129 :     }
     189             : 
     190             :     virtual void Retain()  = 0;
     191             :     virtual void Release() = 0;
     192             : 
     193             :     virtual bool IsActiveSession() const = 0;
     194             : 
     195             :     virtual ScopedNodeId GetPeer() const                                 = 0;
     196             :     virtual ScopedNodeId GetLocalScopedNodeId() const                    = 0;
     197             :     virtual Access::SubjectDescriptor GetSubjectDescriptor() const       = 0;
     198             :     virtual bool AllowsMRP() const                                       = 0;
     199             :     virtual bool AllowsLargePayload() const                              = 0;
     200             :     virtual const SessionParameters & GetRemoteSessionParameters() const = 0;
     201             :     virtual System::Clock::Timestamp GetMRPBaseTimeout() const           = 0;
     202             :     virtual System::Clock::Milliseconds32 GetAckTimeout() const          = 0;
     203             : 
     204        9366 :     const ReliableMessageProtocolConfig & GetRemoteMRPConfig() const { return GetRemoteSessionParameters().GetMRPConfig(); }
     205             : 
     206             :     // Returns a suggested timeout value based on the round-trip time it takes for the peer at the other end of the session to
     207             :     // receive a message, process it and send it back. This is computed based on the session type, the type of transport, sleepy
     208             :     // characteristics of the target and a caller-provided value for the time it takes to process a message at the upper layer on
     209             :     // the target For group sessions, this function will always return 0.
     210             :     System::Clock::Timeout ComputeRoundTripTimeout(System::Clock::Timeout upperlayerProcessingTimeout);
     211             : 
     212       68591 :     FabricIndex GetFabricIndex() const { return mFabricIndex; }
     213             : 
     214             :     SecureSession * AsSecureSession();
     215             :     UnauthenticatedSession * AsUnauthenticatedSession();
     216             :     IncomingGroupSession * AsIncomingGroupSession();
     217             :     OutgoingGroupSession * AsOutgoingGroupSession();
     218             : 
     219       39990 :     bool IsGroupSession() const
     220             :     {
     221       39990 :         return GetSessionType() == SessionType::kGroupIncoming || GetSessionType() == SessionType::kGroupOutgoing;
     222             :     }
     223             : 
     224        9546 :     bool IsSecureSession() const { return GetSessionType() == SessionType::kSecure; }
     225             : 
     226          42 :     bool IsUnauthenticatedSession() const { return GetSessionType() == SessionType::kUnauthenticated; }
     227             : 
     228           8 :     void DispatchSessionEvent(SessionDelegate::Event event)
     229             :     {
     230             :         // Holders might remove themselves when notified.
     231           8 :         auto holder = mHolders.begin();
     232          27 :         while (holder != mHolders.end())
     233             :         {
     234          19 :             auto cur = holder;
     235          19 :             ++holder;
     236          19 :             cur->DispatchSessionEvent(event);
     237             :         }
     238           8 :     }
     239             : 
     240             :     // Return a session id that is usable for logging. This is the local session
     241             :     // id for secure unicast sessions, 0 for non-secure unicast sessions, and
     242             :     // the group id for group sessions.
     243             :     uint16_t SessionIdForLogging() const;
     244             : 
     245             : protected:
     246             :     // This should be called by sub-classes at the very beginning of the destructor, before any data field is disposed, such that
     247             :     // the session is still functional during the callback.
     248      133621 :     void NotifySessionReleased()
     249             :     {
     250      133621 :         SessionHandle session(*this);
     251      133652 :         while (!mHolders.Empty())
     252             :         {
     253          31 :             mHolders.begin()->SessionReleased(); // SessionReleased must remove the item from the linked list
     254             :         }
     255      133621 :     }
     256             : 
     257        1517 :     void SetFabricIndex(FabricIndex index) { mFabricIndex = index; }
     258             : 
     259             :     const SecureSession * AsConstSecureSession() const;
     260             :     const IncomingGroupSession * AsConstIncomingGroupSession() const;
     261             :     const OutgoingGroupSession * AsConstOutgoingGroupSession() const;
     262             : 
     263             :     IntrusiveList<SessionHolder> mHolders;
     264             : 
     265             : private:
     266             :     FabricIndex mFabricIndex = kUndefinedFabricIndex;
     267             : };
     268             : 
     269             : //
     270             : // Return a string representation of the underlying session.
     271             : //
     272             : // Always returns a non-null pointer.
     273             : //
     274             : const char * GetSessionTypeString(const SessionHandle & session);
     275             : 
     276             : } // namespace Transport
     277             : } // namespace chip

Generated by: LCOV version 1.14