// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/socket/websocket_stream_socket.h"

#include <memory>
#include <set>
#include <string>

#include "base/functional/callback_helpers.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket.h"
#include "net/socket/stream_socket.h"
#include "net/socket/websocket_endpoint_lock_manager.h"

namespace net {

WebSocketStreamSocket::WebSocketStreamSocket(
    WebSocketEndpointLockManager& websocket_endpoint_lock_manager,
    const IPEndPoint& endpoint,
    std::unique_ptr<StreamSocket> stream_socket,
    const NetworkAnonymizationKey& network_anonymization_key)
    : wrapped_socket_(std::move(stream_socket)),
      endpoint_lock_(&websocket_endpoint_lock_manager,
                     endpoint,
                     network_anonymization_key) {}

WebSocketStreamSocket::~WebSocketStreamSocket() = default;

int WebSocketStreamSocket::Read(IOBuffer* buf,
                                int buf_len,
                                CompletionOnceCallback callback) {
  return wrapped_socket_->Read(buf, buf_len, std::move(callback));
}

int WebSocketStreamSocket::ReadIfReady(IOBuffer* buf,
                                       int buf_len,
                                       CompletionOnceCallback callback) {
  return wrapped_socket_->ReadIfReady(buf, buf_len, std::move(callback));
}

int WebSocketStreamSocket::CancelReadIfReady() {
  return wrapped_socket_->CancelReadIfReady();
}

int WebSocketStreamSocket::Write(
    IOBuffer* buf,
    int buf_len,
    CompletionOnceCallback callback,
    const NetworkTrafficAnnotationTag& traffic_annotation) {
  return wrapped_socket_->Write(buf, buf_len, std::move(callback),
                                traffic_annotation);
}

int WebSocketStreamSocket::SetReceiveBufferSize(int32_t size) {
  return wrapped_socket_->SetReceiveBufferSize(size);
}

int WebSocketStreamSocket::SetSendBufferSize(int32_t size) {
  return wrapped_socket_->SetSendBufferSize(size);
}

void WebSocketStreamSocket::SetDnsAliases(std::set<std::string> aliases) {
  wrapped_socket_->SetDnsAliases(std::move(aliases));
}

const std::set<std::string>& WebSocketStreamSocket::GetDnsAliases() const {
  return wrapped_socket_->GetDnsAliases();
}

int WebSocketStreamSocket::Connect(CompletionOnceCallback callback) {
  auto [callback1, callback2] = base::SplitOnceCallback(std::move(callback));
  // Unretained is safe here because destroying the EndpointLock will abort any
  // pending lock request, and thus prevent the callback from being invoked.
  int rv = endpoint_lock_.LockEndpoint(
      base::BindOnce(&WebSocketStreamSocket::OnWebSocketEndpointLockObtained,
                     base::Unretained(this), std::move(callback1)));
  if (rv == ERR_IO_PENDING) {
    return rv;
  }
  return wrapped_socket_->Connect(std::move(callback2));
}

void WebSocketStreamSocket::Disconnect() {
  wrapped_socket_->Disconnect();
}

bool WebSocketStreamSocket::IsConnected() const {
  return wrapped_socket_->IsConnected();
}

bool WebSocketStreamSocket::IsConnectedAndIdle() const {
  return wrapped_socket_->IsConnectedAndIdle();
}

int WebSocketStreamSocket::GetPeerAddress(IPEndPoint* address) const {
  return wrapped_socket_->GetPeerAddress(address);
}

int WebSocketStreamSocket::GetLocalAddress(IPEndPoint* address) const {
  return wrapped_socket_->GetLocalAddress(address);
}

const NetLogWithSource& WebSocketStreamSocket::NetLog() const {
  return wrapped_socket_->NetLog();
}

bool WebSocketStreamSocket::WasEverUsed() const {
  return wrapped_socket_->WasEverUsed();
}

NextProto WebSocketStreamSocket::GetNegotiatedProtocol() const {
  return wrapped_socket_->GetNegotiatedProtocol();
}

bool WebSocketStreamSocket::GetSSLInfo(SSLInfo* ssl_info) {
  return wrapped_socket_->GetSSLInfo(ssl_info);
}

int64_t WebSocketStreamSocket::GetTotalReceivedBytes() const {
  return wrapped_socket_->GetTotalReceivedBytes();
}

void WebSocketStreamSocket::ApplySocketTag(const SocketTag& tag) {
  wrapped_socket_->ApplySocketTag(tag);
}

void WebSocketStreamSocket::OnWebSocketEndpointLockObtained(
    CompletionOnceCallback callback) {
  auto [callback1, callback2] = base::SplitOnceCallback(std::move(callback));

  int rv = wrapped_socket_->Connect(std::move(callback1));
  if (rv != ERR_IO_PENDING) {
    std::move(callback2).Run(rv);
  }
}

}  // namespace net
