text: // Copyright 2018 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/core/invitation_dispatcher.h"
  
  #include "mojo/core/core.h"
  
  namespace mojo {
  namespace core {
  
  InvitationDispatcher::InvitationDispatcher() = default;
  
  Dispatcher::Type InvitationDispatcher::GetType() const {
    return Type::INVITATION;
  }
  
  MojoResult InvitationDispatcher::Close() {
    PortMapping attached_ports;
    {
      base::AutoLock lock(lock_);
      if (is_closed_)
        return MOJO_RESULT_INVALID_ARGUMENT;
      is_closed_ = true;
      std::swap(attached_ports, attached_ports_);
    }
    for (auto& entry : attached_ports)
      Core::Get()->GetNodeController()->ClosePort(entry.second);
    return MOJO_RESULT_OK;
  }
  
  MojoResult InvitationDispatcher::AttachMessagePipe(
      base::StringPiece name,
      ports::PortRef remote_peer_port) {
    base::AutoLock lock(lock_);
    auto result = attached_ports_.emplace(name.as_string(), remote_peer_port);
    if (!result.second) {
      Core::Get()->GetNodeController()->ClosePort(remote_peer_port);
      return MOJO_RESULT_ALREADY_EXISTS;
    }
    return MOJO_RESULT_OK;
  }
  
  MojoResult InvitationDispatcher::ExtractMessagePipe(
      base::StringPiece name,
      MojoHandle* message_pipe_handle) {
    ports::PortRef remote_peer_port;
    {
      base::AutoLock lock(lock_);
      auto it = attached_ports_.find(name.as_string());
      if (it == attached_ports_.end())
        return MOJO_RESULT_NOT_FOUND;
      remote_peer_port = std::move(it->second);
      attached_ports_.erase(it);
    }
  
    *message_pipe_handle =
        Core::Get()->CreatePartialMessagePipe(remote_peer_port);
    if (*message_pipe_handle == MOJO_HANDLE_INVALID)
      return MOJO_RESULT_RESOURCE_EXHAUSTED;
    return MOJO_RESULT_OK;
  }
  
  InvitationDispatcher::PortMapping InvitationDispatcher::TakeAttachedPorts() {
    PortMapping attached_ports;
    {
      base::AutoLock lock(lock_);
      std::swap(attached_ports, attached_ports_);
    }
    return attached_ports;
  }
  
  InvitationDispatcher::~InvitationDispatcher() {
    DCHECK(is_closed_);
  }
  
  }  // namespace core
  }  // namespace mojo
  