// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef CORE_INTERNAL_BASE_ENDPOINT_CHANNEL_H_ #define CORE_INTERNAL_BASE_ENDPOINT_CHANNEL_H_ #include #include #include #include "securegcm/d2d_connection_context_v1.h" #include "absl/base/thread_annotations.h" #include "core/internal/endpoint_channel.h" #include "platform/base/byte_array.h" #include "platform/base/input_stream.h" #include "platform/base/output_stream.h" #include "platform/public/atomic_reference.h" #include "platform/public/condition_variable.h" #include "platform/public/mutex.h" #include "platform/public/system_clock.h" namespace location { namespace nearby { namespace connections { class BaseEndpointChannel : public EndpointChannel { public: BaseEndpointChannel(const std::string& channel_name, InputStream* reader, OutputStream* writer); ~BaseEndpointChannel() override = default; ExceptionOr Read() ABSL_LOCKS_EXCLUDED(reader_mutex_, crypto_mutex_, last_read_mutex_) override; Exception Write(const ByteArray& data) ABSL_LOCKS_EXCLUDED(writer_mutex_, crypto_mutex_) override; // Closes this EndpointChannel, without tracking the closure in analytics. void Close() ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; // Closes this EndpointChannel and records the closure with the given reason. void Close(proto::connections::DisconnectionReason reason) override; // Returns a one-word type descriptor for the concrete EndpointChannel // implementation that can be used in log messages; eg: BLUETOOTH, BLE, // WIFI. std::string GetType() const override; // Returns the name of the EndpointChannel. std::string GetName() const override; // Returns the maximum supported transmit packet size(MTU) for the underlying // transport. int GetMaxTransmitPacketSize() const override; // Enables encryption on the EndpointChannel. // Should be called after connection is accepted by both parties, and // before entering data phase, where Payloads may be exchanged. void EnableEncryption(std::shared_ptr context) override; // Disables encryption on the EndpointChannel. void DisableEncryption() override; // True if the EndpointChannel is currently pausing all writes. bool IsPaused() const ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; // Pauses all writes on this EndpointChannel until resume() is called. void Pause() ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; // Resumes any writes on this EndpointChannel that were suspended when pause() // was called. void Resume() ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; // Returns the timestamp (returned by ElapsedRealtime) of the last read from // this endpoint, or -1 if no reads have occurred. absl::Time GetLastReadTimestamp() const ABSL_LOCKS_EXCLUDED(last_read_mutex_) override; protected: virtual void CloseImpl() = 0; private: // Used to sanity check that our frame sizes are reasonable. static constexpr std::int32_t kMaxAllowedReadBytes = 1048576; // 1MB // The default maximum transmit unit/packet size. static constexpr int kDefaultMaxTransmitPacketSize = 65536; // 64 KB bool IsEncryptionEnabledLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(crypto_mutex_); void UnblockPausedWriter() ABSL_EXCLUSIVE_LOCKS_REQUIRED(is_paused_mutex_); void BlockUntilUnpaused() ABSL_EXCLUSIVE_LOCKS_REQUIRED(is_paused_mutex_); void CloseIo() ABSL_NO_THREAD_SAFETY_ANALYSIS; // We need a separate mutex to pritect read timestamp, because if a read // blocks on IO, we don't want timestamp read access to block too. mutable Mutex last_read_mutex_; absl::Time last_read_timestamp_ ABSL_GUARDED_BY(last_read_mutex_) = absl::InfinitePast(); const std::string channel_name_; // The reader and writer are synchronized independently since we can't have // writes waiting on reads that might potentially block forever. Mutex reader_mutex_; InputStream* reader_ ABSL_PT_GUARDED_BY(reader_mutex_); Mutex writer_mutex_; OutputStream* writer_ ABSL_PT_GUARDED_BY(writer_mutex_); // An encryptor/decryptor. May be null. mutable Mutex crypto_mutex_; std::shared_ptr crypto_context_ ABSL_GUARDED_BY(crypto_mutex_) ABSL_PT_GUARDED_BY(crypto_mutex_); mutable Mutex is_paused_mutex_; ConditionVariable is_paused_cond_{&is_paused_mutex_}; // If true, writes should block until this has been set to false. bool is_paused_ ABSL_GUARDED_BY(is_paused_mutex_) = false; }; } // namespace connections } // namespace nearby } // namespace location #endif // CORE_INTERNAL_BASE_ENDPOINT_CHANNEL_H_