// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
//
// 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.

#include <openssl/bio.h>

#if !defined(OPENSSL_NO_SOCK)

#include <fcntl.h>
#include <string.h>
#include <limits.h>

#include <algorithm>

#if !defined(OPENSSL_WINDOWS)
#include <unistd.h>
#else
#include <winsock2.h>
OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
#endif

#include "internal.h"


using namespace bssl;

#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) { return close(sock); }
#endif

static int sock_free(BIO *bio) {
  if (BIO_get_shutdown(bio)) {
    if (BIO_get_init(bio)) {
      closesocket(FromOpaque(bio)->num);
    }
    BIO_set_init(bio, 0);
    BIO_clear_retry_flags(bio);
  }
  return 1;
}

static int sock_read(BIO *b, char *out, int outl) {
  bio_clear_socket_error();
#if defined(OPENSSL_WINDOWS)
  int ret = recv(FromOpaque(b)->num, out, outl, 0);
#else
  int ret = (int)read(FromOpaque(b)->num, out, outl);
#endif
  BIO_clear_retry_flags(b);
  if (ret <= 0) {
    if (bio_socket_should_retry(ret)) {
      BIO_set_retry_read(b);
    }
  }
  return ret;
}

static int sock_write_ex(BIO *b, const char *in, size_t inl,
                         size_t *out_written) {
  bio_clear_socket_error();
#if defined(OPENSSL_WINDOWS)
  inl = std::min(inl, size_t{INT_MAX});
  int ret = send(FromOpaque(b)->num, in, static_cast<int>(inl), 0);
#else
  ssize_t ret = write(FromOpaque(b)->num, in, inl);
#endif
  BIO_clear_retry_flags(b);
  if (ret <= 0) {
    if (bio_socket_should_retry(ret)) {
      BIO_set_retry_write(b);
    }
    return 0;
  }

  *out_written = ret;
  return 1;
}

static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
  switch (cmd) {
    case BIO_C_SET_FD:
      sock_free(b);
      FromOpaque(b)->num = *static_cast<int *>(ptr);
      BIO_set_shutdown(b, static_cast<int>(num));
      BIO_set_init(b, 1);
      return 1;
    case BIO_C_GET_FD:
      if (BIO_get_init(b)) {
        int *out = static_cast<int *>(ptr);
        if (out != nullptr) {
          *out = FromOpaque(b)->num;
        }
        return FromOpaque(b)->num;
      }
      return -1;
    case BIO_CTRL_GET_CLOSE:
      return BIO_get_shutdown(b);
    case BIO_CTRL_SET_CLOSE:
      BIO_set_shutdown(b, static_cast<int>(num));
      return 1;
    case BIO_CTRL_FLUSH:
      return 1;
    default:
      return 0;
  }
}

static const BIO_METHOD methods_sockp = {
    BIO_TYPE_SOCKET,    "socket",
    /*bwrite=*/nullptr, sock_write_ex,
    sock_read,          nullptr /* gets, */,
    sock_ctrl,          nullptr /* create */,
    sock_free,          nullptr /* callback_ctrl */,
};

const BIO_METHOD *BIO_s_socket() { return &methods_sockp; }

BIO *BIO_new_socket(int fd, int close_flag) {
  BIO *ret;

  ret = BIO_new(BIO_s_socket());
  if (ret == nullptr) {
    return nullptr;
  }
  BIO_set_fd(ret, fd, close_flag);
  return ret;
}

// These functions are provided solely for compatibility with software that
// tries to copy and then modify `BIO_s_socket`. See bio.h for details.
// PostgreSQL's use makes several fragile assumptions on `BIO_s_socket`:
//
// - We do not store anything in `BIO_set_data`. (Broken in upstream OpenSSL,
//   which broke PostgreSQL.)
// - We do not store anything in `BIO_set_app_data`.
// - `BIO_s_socket` is implemented internally using the non-`size_t`-clean
//   I/O functions rather than the `size_t`-clean ones.
// - `BIO_METHOD` never gains another function pointer that is used in concert
//   with any of the functions here.
//
// Some other projects doing similar things use `BIO_meth_get_read` and
// `BIO_meth_get_write` and in turn assume that `BIO_s_socket` has not been
// ported to the `size_t`-clean `BIO_read_ex` and `BIO_write_ex`. (Not yet
// implemented in BoringSSL.)
//
// This is hopelessly fragile. PostgreSQL 18 will include a fix to stop using
// these APIs, but older versions and other software remain impacted, so we
// implement these functions, but only support `BIO_s_socket`. For now they just
// return the underlying functions, but if we ever need to break the above
// assumptions, we can return an older, frozen version of `BIO_s_socket`.
// Limiting to exactly one allowed `BIO_METHOD` lets us do this.
//
// These functions are also deprecated in upstream OpenSSL. See
// https://github.com/openssl/openssl/issues/26047
//
// TODO(davidben): Once Folly and all versions of PostgreSQL we care about are
// updated or patched, remove these functions.

int (*BIO_meth_get_write(const BIO_METHOD *method))(BIO *, const char *, int) {
  BSSL_CHECK(method == BIO_s_socket());
  return method->bwrite;
}

int (*BIO_meth_get_read(const BIO_METHOD *method))(BIO *, char *, int) {
  BSSL_CHECK(method == BIO_s_socket());
  return method->bread;
}

int (*BIO_meth_get_gets(const BIO_METHOD *method))(BIO *, char *, int) {
  BSSL_CHECK(method == BIO_s_socket());
  return method->bgets;
}

int (*BIO_meth_get_puts(const BIO_METHOD *method))(BIO *, const char *) {
  BSSL_CHECK(method == BIO_s_socket());
  return nullptr;
}

long (*BIO_meth_get_ctrl(const BIO_METHOD *method))(BIO *, int, long, void *) {
  BSSL_CHECK(method == BIO_s_socket());
  return method->ctrl;
}

int (*BIO_meth_get_create(const BIO_METHOD *method))(BIO *) {
  BSSL_CHECK(method == BIO_s_socket());
  return method->create;
}

int (*BIO_meth_get_destroy(const BIO_METHOD *method))(BIO *) {
  BSSL_CHECK(method == BIO_s_socket());
  return method->destroy;
}

long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *method))(BIO *, int,
                                                             bio_info_cb) {
  BSSL_CHECK(method == BIO_s_socket());
  return method->callback_ctrl;
}

#endif  // OPENSSL_NO_SOCK
