/* Copyright (c) 2014, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include "async_bio.h"

#include <errno.h>
#include <string.h>

#include <openssl/mem.h>


namespace {

extern const BIO_METHOD async_bio_method;

struct async_bio {
  bool datagram;
  size_t read_quota;
  size_t write_quota;
};

async_bio *get_data(BIO *bio) {
  if (bio->method != &async_bio_method) {
    return NULL;
  }
  return (async_bio *)bio->ptr;
}

static int async_write(BIO *bio, const char *in, int inl) {
  async_bio *a = get_data(bio);
  if (a == NULL || bio->next_bio == NULL) {
    return 0;
  }

  if (a->datagram) {
    // Perform writes synchronously; the DTLS implementation drops any packets
    // that failed to send.
    return BIO_write(bio->next_bio, in, inl);
  }

  BIO_clear_retry_flags(bio);

  if (a->write_quota == 0) {
    BIO_set_retry_write(bio);
    errno = EAGAIN;
    return -1;
  }

  if (!a->datagram && (size_t)inl > a->write_quota) {
    inl = a->write_quota;
  }
  int ret = BIO_write(bio->next_bio, in, inl);
  if (ret <= 0) {
    BIO_copy_next_retry(bio);
  } else {
    a->write_quota -= (a->datagram ? 1 : ret);
  }
  return ret;
}

static int async_read(BIO *bio, char *out, int outl) {
  async_bio *a = get_data(bio);
  if (a == NULL || bio->next_bio == NULL) {
    return 0;
  }

  BIO_clear_retry_flags(bio);

  if (a->read_quota == 0) {
    BIO_set_retry_read(bio);
    errno = EAGAIN;
    return -1;
  }

  if (!a->datagram && (size_t)outl > a->read_quota) {
    outl = a->read_quota;
  }
  int ret = BIO_read(bio->next_bio, out, outl);
  if (ret <= 0) {
    BIO_copy_next_retry(bio);
  } else {
    a->read_quota -= (a->datagram ? 1 : ret);
  }
  return ret;
}

static long async_ctrl(BIO *bio, int cmd, long num, void *ptr) {
  if (bio->next_bio == NULL) {
    return 0;
  }
  BIO_clear_retry_flags(bio);
  int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
  BIO_copy_next_retry(bio);
  return ret;
}

static int async_new(BIO *bio) {
  async_bio *a = (async_bio *)OPENSSL_malloc(sizeof(*a));
  if (a == NULL) {
    return 0;
  }
  memset(a, 0, sizeof(*a));
  bio->init = 1;
  bio->ptr = (char *)a;
  return 1;
}

static int async_free(BIO *bio) {
  if (bio == NULL) {
    return 0;
  }

  OPENSSL_free(bio->ptr);
  bio->ptr = NULL;
  bio->init = 0;
  bio->flags = 0;
  return 1;
}

static long async_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
  if (bio->next_bio == NULL) {
    return 0;
  }
  return BIO_callback_ctrl(bio->next_bio, cmd, fp);
}

const BIO_METHOD async_bio_method = {
  BIO_TYPE_FILTER,
  "async bio",
  async_write,
  async_read,
  NULL /* puts */,
  NULL /* gets */,
  async_ctrl,
  async_new,
  async_free,
  async_callback_ctrl,
};

}  // namespace

BIO *async_bio_create() {
  return BIO_new(&async_bio_method);
}

BIO *async_bio_create_datagram() {
  BIO *ret = BIO_new(&async_bio_method);
  if (!ret) {
    return NULL;
  }
  get_data(ret)->datagram = true;
  return ret;
}

void async_bio_allow_read(BIO *bio, size_t count) {
  async_bio *a = get_data(bio);
  if (a == NULL) {
    return;
  }
  a->read_quota += count;
}

void async_bio_allow_write(BIO *bio, size_t count) {
  async_bio *a = get_data(bio);
  if (a == NULL) {
    return;
  }
  a->write_quota += count;
}
