/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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
 *
 *   http://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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "proton/connection_driver.h"
#include "proton/engine.h"
#include "proton/logger.h"
#include "proton/message.h"

#include "libFuzzingEngine.h"

// This fuzzer is a variant of the receive.c proactor example

#define MAX_SIZE 1024

typedef char str[MAX_SIZE];

typedef struct app_data_t {
  str container_id;
  pn_rwbytes_t message_buffer;
  int message_count;
  int received;
} app_data_t;

static void fdc_write(pn_connection_driver_t *driver);
size_t fcd_read(pn_connection_driver_t *driver, uint8_t **data, size_t *size);
static void decode_message(pn_delivery_t *dlv);
static void handle(app_data_t *app, pn_event_t *event);
static void check_condition(pn_event_t *e, pn_condition_t *cond);

// const bool VERBOSE = true;
const bool VERBOSE = false;
// const bool ERRORS = true;
const bool ERRORS = false;

// I could not get rid of the error messages on stderr in any other way
void devnull(intptr_t context, pn_log_subsystem_t sub,  pn_log_level_t sev, const char *message) {}

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
  if (VERBOSE)
    printf("BEGIN LLVMFuzzerTestOneInput\n");
  app_data_t app = {{0}};
  sprintf(app.container_id, "%s:%06x",
           "fuzz_connection_driver", rand() & 0xffffff);

  pn_connection_driver_t driver;
  if (pn_connection_driver_init(&driver, NULL, NULL) != 0) {
    printf("pn_connection_driver_init\n");
    exit(1);
  }

  pn_logger_set_log_sink(pn_default_logger(), devnull, 0);

  uint8_t *data = (uint8_t *)Data;
  size_t size = Size;

  fdc_write(&driver);

  pn_event_t *event;
  while ((event = pn_connection_driver_next_event(&driver)) != NULL) {
    handle(&app, event);
  }

  fdc_write(&driver);

  do {
    fdc_write(&driver);
    fcd_read(&driver, &data, &size);
    if (VERBOSE)
      printf("size is %d, data is %p\n", (int)size, (void *)data);
    while ((event = pn_connection_driver_next_event(&driver)) != NULL) {
      handle(&app, event);
    }
  } while (size > 0);

  pn_connection_driver_close(&driver);
  pn_connection_driver_destroy(&driver);
  if (VERBOSE)
    printf("END LLVMFuzzerTestOneInput\n");
  return 0;
}

static void handle(app_data_t *app, pn_event_t *event) {
  switch (pn_event_type(event)) {

  case PN_CONNECTION_INIT: {
    pn_connection_t *c = pn_event_connection(event);
    pn_connection_set_container(c, app->container_id);
    pn_connection_open(c);
    pn_session_t *s = pn_session(c);
    pn_session_open(s);
    pn_link_t *l = pn_receiver(s, "my_receiver");
    pn_terminus_set_address(pn_link_source(l), NULL);
    pn_link_open(l);
    pn_link_flow(l, 20);
  } break;

  case PN_DELIVERY: {
    /* A message has been received */
    pn_link_t *link = NULL;
    pn_delivery_t *dlv = pn_event_delivery(event);
    if (pn_delivery_readable(dlv) && !pn_delivery_partial(dlv)) {
      link = pn_delivery_link(dlv);
      decode_message(dlv);
      /* Accept the delivery */
      pn_delivery_update(dlv, PN_ACCEPTED);
      /* done with the delivery, move to the next and free it */
      pn_link_advance(link);
      pn_delivery_settle(dlv); /* dlv is now freed */
    }
  } break;

  case PN_TRANSPORT_ERROR:
    check_condition(event, pn_transport_condition(pn_event_transport(event)));
    pn_connection_close(pn_event_connection(event));
    break;

  case PN_CONNECTION_REMOTE_CLOSE:
    check_condition(event,
                    pn_connection_remote_condition(pn_event_connection(event)));
    pn_connection_close(pn_event_connection(event));
    break;

  case PN_SESSION_REMOTE_CLOSE:
    check_condition(event,
                    pn_session_remote_condition(pn_event_session(event)));
    pn_connection_close(pn_event_connection(event));
    break;

  case PN_LINK_REMOTE_CLOSE:
  case PN_LINK_REMOTE_DETACH:
    check_condition(event, pn_link_remote_condition(pn_event_link(event)));
    pn_connection_close(pn_event_connection(event));
    break;

  default:
    break;
  }
}

static void check_condition(pn_event_t *e, pn_condition_t *cond) {
  if (VERBOSE)
    printf("beginning check_condition\n");
  if (pn_condition_is_set(cond)) {
    if (VERBOSE || ERRORS)
      fprintf(stderr, "%s: %s: %s\n", pn_event_type_name(pn_event_type(e)),
              pn_condition_get_name(cond), pn_condition_get_description(cond));
  }
}

static void decode_message(pn_delivery_t *dlv) {
  static char buffer[MAX_SIZE];
  ssize_t len;
  // try to decode the message body
  if (pn_delivery_pending(dlv) < MAX_SIZE) {
    // read in the raw data
    len = pn_link_recv(pn_delivery_link(dlv), buffer, MAX_SIZE);
    if (len > 0) {
      // decode it into a proton message
      pn_message_t *m = pn_message();
      if (PN_OK == pn_message_decode(m, buffer, len)) {
        pn_string_t *s = pn_string(NULL);
        pn_inspect(pn_message_body(m), s);
        if (ERRORS)
          printf("%s\n", pn_string_get(s));
        pn_free(s);
      }
      pn_message_free(m);
    }
  }
}

// reads up to `size` bytes from `data`,
// updates `data` pointer and `size` to the unread portion of original `data`,
// returns new value of `size`
size_t fcd_read(pn_connection_driver_t *driver, uint8_t **data, size_t *size) {
  pn_rwbytes_t buf = pn_connection_driver_read_buffer(driver);
  size_t s = (*size < buf.size) ? *size : buf.size;
  if (buf.start == NULL) {
    // The engine offered a null buffer for further input.
    // This is legit, because it is just that the "socket" was closed
    //  for further input, after reading the invalid header.
    *size = 0;
    return *size;
  }
  memcpy(buf.start, *data, s);

  pn_connection_driver_read_done(driver, s);
  *data += s;
  *size -= s;

  return *size;
}

// drops the data in the buffer and reports them as written
static void fdc_write(pn_connection_driver_t *driver) {
  pn_bytes_t buffer = pn_connection_driver_write_buffer(driver);
  pn_connection_driver_write_done(driver, buffer.size);
}
