// Copyright 2018 The Fuchsia 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 <lib/async/default.h>

#include "garnet/drivers/bluetooth/lib/rfcomm/session.h"
#include "garnet/drivers/bluetooth/lib/common/slab_allocator.h"
#include "garnet/drivers/bluetooth/lib/rfcomm/rfcomm.h"

namespace btlib {
namespace rfcomm {

namespace {

// Timeout system parameters (see RFCOMM 5.3, table 5.1)
//
// T1: timeout for (most) command frames; in RFCOMM, this only applies to SABM
// and DISC frames. 10-60 seconds, recommended value 20 seconds.
constexpr zx::duration kAcknowledgementTimer = zx::sec(20);

// T1': timeout for SABM frames used to start DLCs with DLCI > 0. See RFCOMM
// 5.3. 60-300 seconds.
constexpr zx::duration kAcknowledgementTimerUserDLCs = zx::sec(300);

// T2: timeout for multiplexer commands. 10-60 seconds, recommended value 20
// seconds.
constexpr zx::duration kMuxResponseTimer = zx::sec(20);

// The amount of time the multiplexer will wait when a startup conflict is
// detected. A conflict occurs when the local and remote multiplexers attempt to
// start at the same time. After delaying by the below amount, the local
// multiplexer will attempt to start up the multiplexer again. see RFCOMM 5.2.1.
constexpr zx::duration kMuxStartupConflictDelay = zx::msec(20);

// Used to indicate that an outstanding multiplexer command does not pertain to
// any specific DLCI. This is applicable for multiplexer commands such as the
// Test command.
static constexpr DLCI kNoDLCI = 1;  // 1 is an invalid DLCI.

// Given a multiplexer command, find the DLCI which this command pertains to.
// Commands such as DLC Parameter Negotiation (PN) pertain to specific DLCs,
// whereas commands like the Test command or FCon/FCoff commands do not.
// Returns kNoDLCI for those commands which do not pertain to a specific DLCI.
DLCI GetDLCIFromMuxCommand(MuxCommand* mux_command) {
  MuxCommandType type = mux_command->command_type();
  switch (type) {
    case MuxCommandType::kDLCParameterNegotiation:
      return static_cast<DLCParameterNegotiationCommand*>(mux_command)
          ->params()
          .dlci;
    case MuxCommandType::kModemStatusCommand:
      return static_cast<ModemStatusCommand*>(mux_command)->dlci();
    case MuxCommandType::kRemoteLineStatusCommand:
      return static_cast<RemoteLineStatusCommand*>(mux_command)->dlci();
    case MuxCommandType::kRemotePortNegotiationCommand:
      return static_cast<RemotePortNegotiationCommand*>(mux_command)->dlci();
    case MuxCommandType::kFlowControlOffCommand:
    case MuxCommandType::kFlowControlOnCommand:
    case MuxCommandType::kTestCommand:
    case MuxCommandType::kNonSupportedCommandResponse:
      return kNoDLCI;
    default:
      FXL_LOG(ERROR) << "Unexpected multiplexer command type";
      return kNoDLCI;
  }
}

}  // namespace

std::unique_ptr<Session> Session::Create(
    fbl::RefPtr<l2cap::Channel> l2cap_channel,
    ChannelOpenedCallback channel_opened_cb) {
  auto session =
      std::unique_ptr<Session>(new Session(std::move(channel_opened_cb)));
  if (!session->SetL2CAPChannel(l2cap_channel))
    return nullptr;
  return session;
}

Session::Session(ChannelOpenedCallback channel_opened_cb)
    : role_(Role::kUnassigned),
      channel_opened_cb_(std::move(channel_opened_cb)),
      dispatcher_(async_get_default_dispatcher()),
      initial_param_negotiation_state_(
          ParameterNegotiationState::kNotNegotiated),
      weak_ptr_factory_(this) {}

bool Session::SetL2CAPChannel(fbl::RefPtr<l2cap::Channel> l2cap_channel) {
  FXL_DCHECK(!l2cap_channel_);
  FXL_DCHECK(l2cap_channel);
  l2cap_channel_.Reset(l2cap_channel);
  auto self = weak_ptr_factory_.GetWeakPtr();
  return l2cap_channel_->Activate(
      [self](const auto& sdu) {
        if (self)
          self->RxCallback(sdu);
      },
      [self]() {
        if (self)
          self->ClosedCallback();
      },
      dispatcher_);
}

void Session::OpenRemoteChannel(ServerChannel server_channel,
                                ChannelOpenedCallback channel_opened_cb) {
  if (!multiplexer_started()) {
    tasks_pending_mux_startup_.emplace(
        [this, server_channel, cb = std::move(channel_opened_cb)]() mutable {
          OpenRemoteChannel(server_channel, std::move(cb));
        });
    if (role_ == Role::kUnassigned)
      StartupMultiplexer();
    return;
  }

  DLCI dlci = ServerChannelToDLCI(server_channel, role_);

  if (initial_param_negotiation_state_ !=
      ParameterNegotiationState::kNegotiated) {
    tasks_pending_parameter_negotiation_.emplace(
        [this, server_channel, cb = std::move(channel_opened_cb)]() mutable {
          OpenRemoteChannel(server_channel, std::move(cb));
        });

    // If it's not started, start it
    if (initial_param_negotiation_state_ ==
        ParameterNegotiationState::kNotNegotiated)
      RunInitialParameterNegotiation(dlci);

    return;
  }

  // TODO(NET-1013): implement channel open

  // Return a nullptr channel if we fail to open
  FXL_LOG(WARNING) << "Not implemented";
  async::PostTask(dispatcher_, [cb = std::move(channel_opened_cb)] {
    cb(nullptr, kInvalidServerChannel);
  });
}

void Session::RxCallback(const l2cap::SDU& sdu) {
  l2cap::PDU::Reader reader(&sdu);
  reader.ReadNext(sdu.length(), [&](const common::ByteBuffer& buffer) {
    auto frame = Frame::Parse(credit_based_flow_, OppositeRole(role_), buffer);
    if (!frame) {
      FXL_LOG(ERROR) << "Could not parse frame";
      return;
    }

    DLCI dlci = frame->dlci();

    switch ((FrameType)frame->control()) {
      case FrameType::kSetAsynchronousBalancedMode:
        HandleSABM(dlci);
        return;

      case FrameType::kUnnumberedAcknowledgement:
      case FrameType::kDisconnectedMode: {
        auto callbacks_it = outstanding_frames_.find(dlci);
        if (callbacks_it == outstanding_frames_.end()) {
          FXL_NOTIMPLEMENTED() << "Unsolicited UA or DM frame";
          return;
        }

        // Cancel the timeout and run the callback.
        callbacks_it->second.second->Cancel();
        async::PostTask(
            dispatcher_,
            [cb = std::move(callbacks_it->second.first),
             fr = std::move(frame)]() mutable { cb(std::move(fr)); });

        outstanding_frames_.erase(dlci);

        return;
      }

      case FrameType::kUnnumberedInfoHeaderCheck: {
        if (dlci == kMuxControlDLCI) {
          HandleMuxCommand(
              static_cast<MuxCommandFrame*>(frame.get())->TakeMuxCommand());
          return;
        } else {
          FXL_NOTIMPLEMENTED();
        }
      }

      default:
        // TODO(gusss): implement better error handling here.
        FXL_LOG(WARNING) << "rfcomm: Unrecognized frame type received: "
                         << (unsigned)frame->control();
        return;
    }
  });
}

void Session::ClosedCallback() { Closedown(); }

void Session::SendCommand(FrameType frame_type, DLCI dlci,
                          CommandResponseCallback command_response_cb) {
  FXL_DCHECK(frame_type == FrameType::kSetAsynchronousBalancedMode ||
             frame_type == FrameType::kDisconnect);
  FXL_DCHECK(IsValidDLCI(dlci));
  FXL_DCHECK(outstanding_frames_.find(dlci) == outstanding_frames_.end())
      << "rfcomm: There is already an outstanding command frame for DLCI "
      << static_cast<unsigned>(dlci);

  auto timeout_cb = std::make_unique<async::TaskClosure>([this, dlci] {
    FXL_LOG(ERROR) << "rfcomm: Outstanding frame on DLCI "
                   << static_cast<unsigned>(dlci)
                   << " timed out; closing down session";
    Closedown();
  });

  // Set response and timeout callbacks.
  auto callbacks =
      std::make_pair(std::move(command_response_cb), std::move(timeout_cb));
  outstanding_frames_.emplace(dlci, std::move(callbacks));

  // A different timeout is used if this is a SABM command on a user data
  // channel (RFCOMM 5.3).
  zx::duration timeout =
      (frame_type == FrameType::kSetAsynchronousBalancedMode &&
       IsUserDLCI(dlci))
          ? kAcknowledgementTimerUserDLCs
          : kAcknowledgementTimer;

  std::unique_ptr<Frame> frame;
  if (frame_type == FrameType::kSetAsynchronousBalancedMode) {
    frame = std::make_unique<SetAsynchronousBalancedModeCommand>(role_, dlci);
  } else {
    frame = std::make_unique<DisconnectCommand>(role_, dlci);
  }

  bool sent = SendFrame(std::move(frame), [this, timeout, dlci] {
    outstanding_frames_[dlci].second->PostDelayed(dispatcher_, timeout);
  });
  FXL_DCHECK(sent);
}

void Session::SendResponse(FrameType frame_type, DLCI dlci) {
  FXL_DCHECK(frame_type == FrameType::kUnnumberedAcknowledgement ||
             frame_type == FrameType::kDisconnectedMode);
  FXL_DCHECK(IsValidDLCI(dlci));

  std::unique_ptr<Frame> frame;
  if (frame_type == FrameType::kUnnumberedAcknowledgement)
    frame = std::make_unique<UnnumberedAcknowledgementResponse>(role_, dlci);
  else
    frame = std::make_unique<DisconnectedModeResponse>(role_, dlci);

  bool sent = SendFrame(std::move(frame));
  FXL_DCHECK(sent);
}

bool Session::SendFrame(std::unique_ptr<Frame> frame, fit::closure sent_cb) {
  FXL_DCHECK(frame);
  const DLCI dlci = frame->dlci();
  const FrameType type = static_cast<FrameType>(frame->control());

  // If the multiplexer isn't started, only startup frames should be sent.
  FXL_DCHECK(multiplexer_started() || IsMuxStartupFrame(type, dlci));

  // TODO(gusss): check that the DLC is actually open.

  // TODO(NET-1079, NET-1080): check flow control and queue the frame if it
  // needs to be queued.

  // TODO(gusss): attach credits to frame.

  // Allocate and write the buffer.
  auto buffer = common::NewSlabBuffer(frame->written_size());
  if (!buffer) {
    FXL_LOG(WARNING) << "rfcomm: Couldn't allocate frame buffer ("
                     << frame->written_size() << ")";
    return false;
  }
  frame->Write(buffer->mutable_view());

  if (l2cap_channel_->Send(std::move(buffer))) {
    if (sent_cb)
      sent_cb();
    return true;
  } else {
    FXL_LOG(ERROR) << "rfcomm: Failed to send frame";
    return false;
  }
}

void Session::SendMuxCommand(std::unique_ptr<MuxCommand> mux_command,
                             MuxResponseCallback callback) {
  FXL_DCHECK(mux_command);

  // If we're not expecting a response, we can send right away.
  if (!callback) {
    auto frame = std::make_unique<MuxCommandFrame>(role_, credit_based_flow_,
                                                   std::move(mux_command));
    bool sent = SendFrame(std::move(frame));
    FXL_DCHECK(sent);
    return;
  }

  // If we're expecting a response at the mulitplexer level, store the callback
  // that should be called when the response arrives.
  MuxCommandType type = mux_command->command_type();
  DLCI dlci = GetDLCIFromMuxCommand(mux_command.get());
  OutstandingMuxCommand key = std::make_pair(type, dlci);

  FXL_DCHECK(outstanding_mux_commands_.find(key) ==
             outstanding_mux_commands_.end())
      << "rfcomm: Already an outstanding mux command for (command type,"
      << " dlci) = (" << static_cast<unsigned>(type) << ", "
      << static_cast<unsigned>(dlci) << ")";

  auto timeout_cb =
      std::make_unique<async::TaskClosure>([this] { Closedown(); });

  // Set response and timeout callbacks.
  outstanding_mux_commands_.emplace(
      key, std::make_pair(std::move(callback), std::move(timeout_cb)));

  auto frame = std::make_unique<MuxCommandFrame>(role_, credit_based_flow_,
                                                 std::move(mux_command));

  bool sent = SendFrame(std::move(frame), [this, key] {
    outstanding_mux_commands_[key].second->PostDelayed(dispatcher_,
                                                       kMuxResponseTimer);
  });
  FXL_DCHECK(sent);
}

void Session::StartupMultiplexer() {
  if (role_ == Role::kNegotiating || multiplexer_started()) {
    FXL_LOG(WARNING) << "rfcomm: StartupMultiplexer when starting or started";
    return;
  }

  FXL_LOG(INFO) << "rfcomm: Starting multiplexer";

  role_ = Role::kNegotiating;

  SendCommand(FrameType::kSetAsynchronousBalancedMode, kMuxControlDLCI,
              [this](auto response) {
                FXL_DCHECK(response);

                FrameType type = static_cast<FrameType>(response->control());
                FXL_DCHECK(type == FrameType::kUnnumberedAcknowledgement ||
                           type == FrameType::kDisconnectedMode);

                switch (role_) {
                  case Role::kNegotiating: {
                    if (type == FrameType::kUnnumberedAcknowledgement) {
                      SetMultiplexerStarted(Role::kInitiator);
                    } else {
                      FXL_LOG(WARNING)
                          << "rfcomm: Remote multiplexer startup refused"
                          << " by remote";
                      role_ = Role::kUnassigned;
                    }
                    return;
                  }
                  case Role::kUnassigned:
                  case Role::kInitiator:
                  case Role::kResponder:
                    // TODO(guss): should a UA be received in any of these
                    // cases?
                    FXL_LOG(WARNING)
                        << "rfcomm: Mux UA frame received in unexpected"
                        << " state";
                    break;
                  default:
                    // TODO(gusss): shouldn't get here.
                    FXL_NOTREACHED();
                    break;
                }
              });
}

void Session::HandleSABM(DLCI dlci) {
  if (dlci == kMuxControlDLCI) {
    // A SABM frame on the mux control DLCI indicates that we should start
    // up the multiplexer.
    switch (role_) {
      case Role::kUnassigned: {
        // We received a SABM request to start the multiplexer. Reply positively
        // to the request, meaning that the peer becomes the initiator and this
        // session becomes the responder.
        SendResponse(FrameType::kUnnumberedAcknowledgement, dlci);
        SetMultiplexerStarted(Role::kResponder);
        return;
      }
      case Role::kNegotiating: {
        // In this case, we have an outstanding request to start the
        // multiplexer. Respond negatively and attempt startup again later. See
        // RFCOMM 5.2.1.

        FXL_LOG(INFO) << "rfcomm: Resolving multiplexer startup conflict";

        // "Undo" our multiplexer startup request by changing our role back,
        // cancelling timeout, and removing callbacks.
        role_ = Role::kUnassigned;
        auto frame_it = outstanding_frames_.find(dlci);
        FXL_DCHECK(frame_it != outstanding_frames_.end());
        frame_it->second.second->Cancel();
        outstanding_frames_.erase(frame_it);

        SendResponse(FrameType::kDisconnectedMode, kMuxControlDLCI);
        async::PostDelayedTask(
            dispatcher_,
            [this] {
              if (!multiplexer_started()) {
                FXL_LOG(INFO) << "rfcomm: Retrying multiplexer startup";
                StartupMultiplexer();
              }
            },
            kMuxStartupConflictDelay);
        return;
      }
      case Role::kInitiator:
      case Role::kResponder:
        // TODO(gusss): should we send a DM in this case?
        FXL_LOG(WARNING) << "rfcomm: Request to start alreadys started"
                         << " multiplexer";
        return;
      default:
        FXL_NOTREACHED();
        return;
    }
  } else {
    // TODO(NET-1014): open channel when requested by remote peer
    FXL_NOTIMPLEMENTED();
  }
}

void Session::HandleMuxCommand(std::unique_ptr<MuxCommand> mux_command) {
  FXL_DCHECK(mux_command);
  MuxCommandType type = mux_command->command_type();

  if (mux_command->command_response() == CommandResponse::kResponse) {
    auto dlci = GetDLCIFromMuxCommand(mux_command.get());
    auto key = std::make_pair(type, dlci);

    auto command_it = outstanding_mux_commands_.find(key);
    if (command_it == outstanding_mux_commands_.end()) {
      FXL_LOG(WARNING)
          << "Got response, but no outstanding command for (type, DLCI) = "
          << "(" << unsigned(type) << ", " << unsigned(dlci) << ")";
      return;
    }

    // Cancel the timeout and call the callback.
    command_it->second.second->Cancel();
    async::PostTask(
        dispatcher_,
        [cmd = std::move(mux_command),
         cb = std::move(outstanding_mux_commands_[key].first)]() mutable {
          cb(std::move(cmd));
        });

    outstanding_mux_commands_.erase(command_it);

    return;
  }

  // Otherwise, it's a command.
  switch (type) {
    case MuxCommandType::kDLCParameterNegotiation: {
      auto pn_command = std::unique_ptr<DLCParameterNegotiationCommand>(
          static_cast<DLCParameterNegotiationCommand*>(mux_command.release()));
      ParameterNegotiationParams received_params = pn_command->params();

      if (!IsUserDLCI(received_params.dlci)) {
        FXL_LOG(WARNING)
            << "rfcomm: Received parameter negotiation command for invalid"
            << " DLCI " << static_cast<unsigned>(received_params.dlci);
        SendResponse(FrameType::kDisconnectedMode, received_params.dlci);
        return;
      }

      if (channels_negotiating_.find(received_params.dlci) !=
              channels_negotiating_.end() &&
          channels_negotiating_[received_params.dlci] !=
              ParameterNegotiationState::kNotNegotiated) {
        // RFCOMM 5.5.3 states that supporting re-negotiation of DLCIs is
        // optional, and that instead we may just reply with our own parameters.
        FXL_LOG(WARNING)
            << "rfcomm: Request to negotiate already-negotiated DLCI";
        SendResponse(FrameType::kDisconnectedMode, received_params.dlci);
        ParameterNegotiationParams our_params =
            GetIdealParameters(received_params.dlci);
        our_params.credit_based_flow_handshake =
            CreditBasedFlowHandshake::kSupportedResponse;
        our_params.maximum_frame_size = maximum_frame_size_;
        SendMuxCommand(std::make_unique<DLCParameterNegotiationCommand>(
            CommandResponse::kResponse, our_params));
        return;
      }

      if (initial_param_negotiation_state_ ==
              ParameterNegotiationState::kNegotiated &&
          received_params.maximum_frame_size != maximum_frame_size_) {
        // RFCOMM 5.5.3 states that a responder may issue a DM frame if they are
        // unwilling to establish a connection. In this case, we use it to
        // reject any non-initial PN command which attempts to change the
        // maximum frame size.
        FXL_LOG(WARNING) << "rfcomm: Peer requested different max frame size"
                         << " after initial negotiation complete; rejecting";
        SendResponse(FrameType::kDisconnectedMode, received_params.dlci);
        return;
      }

      ParameterNegotiationParams ideal_params =
          GetIdealParameters(received_params.dlci);

      // Parameter negotiation described in GSM 5.4.6.3.1 (under table 5).
      ParameterNegotiationParams negotiated_params;
      // DLCI does not change.
      negotiated_params.dlci = received_params.dlci;
      // Respond with a positive credit-based flow handshake response iff we
      // received a positive request.
      negotiated_params.credit_based_flow_handshake =
          received_params.credit_based_flow_handshake ==
                  CreditBasedFlowHandshake::kSupportedRequest
              ? CreditBasedFlowHandshake::kSupportedResponse
              : CreditBasedFlowHandshake::kUnsupported;
      // Priority does not change.
      negotiated_params.priority = received_params.priority;

      // Accept their max frame size if this is the initial negotiation and if
      // it's less than or equal to ours; otherwise, use ours.
      if (initial_param_negotiation_state_ !=
          ParameterNegotiationState::kNegotiated) {
        negotiated_params.maximum_frame_size =
            received_params.maximum_frame_size <=
                    ideal_params.maximum_frame_size
                ? received_params.maximum_frame_size
                : ideal_params.maximum_frame_size;
      } else {
        FXL_DCHECK(received_params.maximum_frame_size == maximum_frame_size_);
        negotiated_params.maximum_frame_size = maximum_frame_size_;
      }

      negotiated_params.initial_credits = ideal_params.initial_credits;

      // Update settings.

      if (initial_param_negotiation_state_ !=
          ParameterNegotiationState::kNegotiated) {
        // Set credit-based flow and max frame size only on initial PN.
        credit_based_flow_ = received_params.credit_based_flow_handshake ==
                             CreditBasedFlowHandshake::kSupportedRequest;
        maximum_frame_size_ = negotiated_params.maximum_frame_size;
        InitialParameterNegotiationComplete();
      }

      // TODO(NET-1130): set priority if/when priority is implemented.

      // TODO(NET-1079): receive credits when credit-based flow is implemented.

      FXL_LOG(INFO) << "rfcomm: Parameters negotiated:"
                    << " DLCI " << unsigned(negotiated_params.dlci) << ","
                    << " Credit-based flow "
                    << (negotiated_params.credit_based_flow_handshake ==
                                CreditBasedFlowHandshake::kSupportedResponse
                            ? "on,"
                            : "off,")
                    << " (credits "
                    << static_cast<unsigned>(negotiated_params.initial_credits)
                    << "),"
                    << " Priority "
                    << static_cast<unsigned>(negotiated_params.priority) << ","
                    << " Max frame size "
                    << negotiated_params.maximum_frame_size;

      // Respond with the negotiated params.
      SendMuxCommand(std::make_unique<DLCParameterNegotiationCommand>(
          CommandResponse::kResponse, negotiated_params));

      channels_negotiating_[negotiated_params.dlci] =
          ParameterNegotiationState::kNegotiated;

      return;
    }
    default: {
      FXL_NOTIMPLEMENTED();
      break;
    }
  }
}

void Session::SetMultiplexerStarted(Role role) {
  FXL_DCHECK(role == Role::kInitiator || role == Role::kResponder);

  role_ = role;
  FXL_LOG(INFO) << "rfcomm: Multiplexer started. Role: "
                << (role == Role::kInitiator ? "initiator" : "responder");

  // Run any pending tasks.
  while (!tasks_pending_mux_startup_.empty()) {
    async::PostTask(dispatcher_, std::move(tasks_pending_mux_startup_.front()));
    tasks_pending_mux_startup_.pop();
  }

  // TODO(gusss): send frames from queue when queueing implemented
}

void Session::Closedown() {
  FXL_LOG(INFO) << "rfcomm: Closing session";
  // Deactivates the channel.
  l2cap_channel_ = nullptr;
}

void Session::RunInitialParameterNegotiation(DLCI dlci) {
  FXL_DCHECK(multiplexer_started())
      << "Parameter negotiation requested before multiplexer started";
  FXL_DCHECK(initial_param_negotiation_state_ ==
             ParameterNegotiationState::kNotNegotiated)
      << "Initial parameter negotiation already run";

  // Mark the DLCI as in the negotiating state.
  channels_negotiating_[dlci] = ParameterNegotiationState::kNegotiating;
  initial_param_negotiation_state_ = ParameterNegotiationState::kNegotiating;

  auto params = GetIdealParameters(dlci);

  auto pn_command = std::make_unique<DLCParameterNegotiationCommand>(
      CommandResponse::kCommand, params);
  SendMuxCommand(std::move(pn_command), [this, dlci, priority = params.priority,
                                         maximum_frame_size =
                                             params.maximum_frame_size](
                                            auto mux_command) {
    FXL_DCHECK(initial_param_negotiation_state_ ==
                   ParameterNegotiationState::kNegotiating ||
               initial_param_negotiation_state_ ==
                   ParameterNegotiationState::kNegotiated);

    if (mux_command == nullptr) {
      // A response of nullptr signals a DM response from the peer.
      FXL_LOG(INFO) << "rfcomm: PN command for DLCI "
                    << static_cast<unsigned>(dlci) << " rejected";
      channels_negotiating_[dlci] = ParameterNegotiationState::kNotNegotiated;

      // If initial parameter negotiation didn't already finish since we started
      // this PN command, then reset it back to kNotNegotiated.
      if (initial_param_negotiation_state_ ==
          ParameterNegotiationState::kNegotiating)
        initial_param_negotiation_state_ =
            ParameterNegotiationState::kNotNegotiated;
      return;
    }

    FXL_DCHECK(mux_command->command_type() ==
                   MuxCommandType::kDLCParameterNegotiation &&
               mux_command->command_response() == CommandResponse::kResponse);

    auto pn_response = std::unique_ptr<DLCParameterNegotiationCommand>(
        static_cast<DLCParameterNegotiationCommand*>(mux_command.release()));
    auto params = pn_response->params();

    if (dlci != params.dlci) {
      FXL_LOG(WARNING) << "rfcomm: Remote changed DLCI in PN response";
      SendCommand(FrameType::kDisconnect, dlci);
      channels_negotiating_[dlci] = ParameterNegotiationState::kNotNegotiated;
      if (initial_param_negotiation_state_ ==
          ParameterNegotiationState::kNegotiating)
        initial_param_negotiation_state_ =
            ParameterNegotiationState::kNotNegotiated;
      return;
    }

    // TODO(gusss): currently we completely ignore priority (other than this
    // check)
    if (params.priority != priority)
      FXL_LOG(WARNING) << "rfcomm: Remote changed priority in PN response";

    if (params.maximum_frame_size > maximum_frame_size) {
      FXL_LOG(WARNING)
          << "rfcomm: Peer's PN response contained an invalid max frame size";
      SendCommand(FrameType::kDisconnect, dlci);
      channels_negotiating_[dlci] = ParameterNegotiationState::kNotNegotiated;
      if (initial_param_negotiation_state_ ==
          ParameterNegotiationState::kNegotiating)
        initial_param_negotiation_state_ =
            ParameterNegotiationState::kNotNegotiated;
      return;
    }

    if (initial_param_negotiation_state_ ==
            ParameterNegotiationState::kNegotiated &&
        params.maximum_frame_size != maximum_frame_size_) {
      FXL_LOG(WARNING)
          << "rfcomm: Peer tried to change max frame size after initial param"
          << " negotiation completed; rejecting";
      SendCommand(FrameType::kDisconnect, dlci);
      channels_negotiating_[dlci] = ParameterNegotiationState::kNotNegotiated;
      if (initial_param_negotiation_state_ ==
          ParameterNegotiationState::kNegotiating)
        initial_param_negotiation_state_ =
            ParameterNegotiationState::kNotNegotiated;
      return;
    }

    // Only set these parameters on initial parameter negotiation.
    if (initial_param_negotiation_state_ ==
        ParameterNegotiationState::kNegotiating) {
      // Credit-based flow is turned on if the peer sends the correct
      // response.
      credit_based_flow_ = params.credit_based_flow_handshake ==
                           CreditBasedFlowHandshake::kSupportedResponse;

      maximum_frame_size_ = params.maximum_frame_size;
      InitialParameterNegotiationComplete();
    }

    // TODO(NET-1079): Handle credits here when credit-based flow implemented
    // HandleReceivedCredits(dlci, params.initial_credits);

    FXL_LOG(INFO) << "rfcomm: Parameters negotiated:"
                  << " DLCI " << unsigned(params.dlci) << ","
                  << " Credit-based flow "
                  << (credit_based_flow_ ? "on" : "off") << " (credits "
                  << static_cast<unsigned>(params.initial_credits) << "),"
                  << " Priority " << static_cast<unsigned>(params.priority)
                  << ","
                  << " Max frame size " << maximum_frame_size_;

    // Set channel to not negotiating anymore.
    FXL_DCHECK(channels_negotiating_.find(dlci) != channels_negotiating_.end());
    channels_negotiating_[dlci] = ParameterNegotiationState::kNegotiated;
  });
}

ParameterNegotiationParams Session::GetIdealParameters(DLCI dlci) const {
  FXL_DCHECK(IsValidDLCI(dlci));

  // We set the MTU of the RFCOMM channel based on the MTUs of the underlying
  // L2CAP link; we take the minimum of the two.
  uint16_t maximum_frame_size =
      (l2cap_channel_->rx_mtu() < l2cap_channel_->tx_mtu()
           ? l2cap_channel_->rx_mtu()
           : l2cap_channel_->tx_mtu());

  // GSM Table 27.
  Priority priority = 61;
  if (dlci == kMuxControlDLCI) {
    priority = 0;
  } else if (dlci <= 7) {
    priority = 7;
  } else if (dlci <= 15) {
    priority = 15;
  } else if (dlci <= 23) {
    priority = 23;
  } else if (dlci <= 31) {
    priority = 31;
  } else if (dlci <= 39) {
    priority = 39;
  } else if (dlci <= 47) {
    priority = 47;
  } else if (dlci <= 55) {
    priority = 55;
  }

  return {dlci,
          // We always attempt to enable credit-based flow (RFCOMM 5.5.3).
          CreditBasedFlowHandshake::kSupportedRequest,
          // TODO(NET-1079): send initial credits when credit-based flow
          // implemented.
          priority, maximum_frame_size, 0};
}

void Session::InitialParameterNegotiationComplete() {
  FXL_LOG(INFO) << "rfcomm: Initial parameter negotiation complete";

  initial_param_negotiation_state_ = ParameterNegotiationState::kNegotiated;

  while (!tasks_pending_parameter_negotiation_.empty()) {
    async::PostTask(dispatcher_,
                    std::move(tasks_pending_parameter_negotiation_.front()));
    tasks_pending_parameter_negotiation_.pop();
  }

  // TODO(gusss): send frames from queue when queueing is implemented.
}

}  // namespace rfcomm
}  // namespace btlib
