blob: 3d7b8d1908dc29d1b1c03e6576f63d22d0cf16ee [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/edk/system/endpoint_relayer.h"
#include <utility>
#include "base/logging.h"
#include "mojo/edk/system/channel_endpoint.h"
#include "mojo/edk/system/message_in_transit.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {
// static
unsigned EndpointRelayer::GetPeerPort(unsigned port) {
DCHECK(port == 0 || port == 1);
return port ^ 1;
}
void EndpointRelayer::Init(RefPtr<ChannelEndpoint>&& endpoint0,
RefPtr<ChannelEndpoint>&& endpoint1) {
DCHECK(endpoint0);
DCHECK(endpoint1);
DCHECK(!endpoints_[0]);
DCHECK(!endpoints_[1]);
endpoints_[0] = std::move(endpoint0);
endpoints_[1] = std::move(endpoint1);
}
void EndpointRelayer::SetFilter(std::unique_ptr<Filter> filter) {
MutexLocker locker(&mutex_);
filter_ = std::move(filter);
}
bool EndpointRelayer::OnReadMessage(unsigned port, MessageInTransit* message) {
DCHECK(message);
MutexLocker locker(&mutex_);
// If we're no longer the client, then reject the message.
if (!endpoints_[port])
return false;
unsigned peer_port = GetPeerPort(port);
if (filter_ && message->type() == MessageInTransit::Type::ENDPOINT_CLIENT) {
if (filter_->OnReadMessage(endpoints_[port].get(),
endpoints_[peer_port].get(), message))
return true;
}
// Otherwise, consume it even if the peer port is closed.
if (endpoints_[peer_port]) {
endpoints_[peer_port]->EnqueueMessage(
std::unique_ptr<MessageInTransit>(message));
}
return true;
}
void EndpointRelayer::OnDetachFromChannel(unsigned port) {
MutexLocker locker(&mutex_);
if (endpoints_[port]) {
endpoints_[port]->DetachFromClient();
endpoints_[port] = nullptr;
}
unsigned peer_port = GetPeerPort(port);
if (endpoints_[peer_port]) {
endpoints_[peer_port]->DetachFromClient();
endpoints_[peer_port] = nullptr;
}
}
EndpointRelayer::EndpointRelayer() {}
EndpointRelayer::~EndpointRelayer() {
DCHECK(!endpoints_[0]);
DCHECK(!endpoints_[1]);
}
} // namespace system
} // namespace mojo