| // 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 <cstdint> |
| #include <memory> |
| #include <string> |
| |
| #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" |
| #include "proto/connections_enums.pb.h" |
| #include "securegcm/d2d_connection_context_v1.h" |
| #include "third_party/absl/base/thread_annotations.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<ByteArray> 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<EncryptionContext> 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<EncryptionContext> 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_ |