blob: 52b12b8d6180910fdb2edfd3802da3b3bd14fcd0 [file] [log] [blame]
// 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_