/*
     This file is part of GNUnet.
     Copyright (C) 2009-2014 GNUnet e.V.

     GNUnet is free software: you can redistribute it and/or modify it
     under the terms of the GNU Affero General Public License as published
     by the Free Software Foundation, either version 3 of the License,
     or (at your option) any later version.

     GNUnet is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     Affero General Public License for more details.

     You should have received a copy of the GNU Affero General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

     SPDX-License-Identifier: AGPL3.0-or-later
 */

/**
 * @file core/core.h
 * @brief common internal definitions for core service
 * @author Christian Grothoff
 */
#ifndef CORE_H
#define CORE_H

#include "gnunet_util_lib.h"
#include "gnunet_time_lib.h"

/**
 * General core debugging.
 */
#define DEBUG_CORE GNUNET_EXTRA_LOGGING

/**
 * Definition of bits in the InitMessage's options field that specify
 * which events this client cares about.  Note that inbound messages
 * for handlers that were specifically registered are always
 * transmitted to the client.
 */
#define GNUNET_CORE_OPTION_NOTHING 0

/**
 * Client cares about connectivity changes.
 */
#define GNUNET_CORE_OPTION_SEND_STATUS_CHANGE 4

/**
 * Client wants all inbound messages in full.
 */
#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 8

/**
 * Client just wants the 4-byte message headers of
 * all inbound messages.
 */
#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 16

/**
 * Client wants all outbound messages in full.
 */
#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32

/**
 * Client just wants the 4-byte message headers of
 * all outbound messages.
 */
#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 64


GNUNET_NETWORK_STRUCT_BEGIN

/**
 * Message transmitted core clients to gnunet-service-core
 * to start the interaction.  This header is followed by
 * uint16_t type values specifying which messages this
 * client is interested in.
 */
struct InitMessage
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT.
   */
  struct GNUNET_MessageHeader header;

  /**
   * Options, see GNUNET_CORE_OPTION_ values.
   */
  uint32_t options GNUNET_PACKED;
};


/**
 * Message transmitted by the gnunet-service-core process
 * to its clients in response to an INIT message.
 */
struct InitReplyMessage
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY
   */
  struct GNUNET_MessageHeader header;

  /**
   * Always zero.
   */
  uint32_t reserved GNUNET_PACKED;

  /**
   * Public key of the local peer.
   */
  struct GNUNET_PeerIdentity my_identity;

  /**
   * Class of the peer
   * TODO is it correct to send an enum like this?
   */
  enum GNUNET_CORE_PeerClass class;
};


/**
 * Message sent by the service to clients to notify them
 * about a peer connecting.
 */
struct ConnectNotifyMessage
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
   */
  struct GNUNET_MessageHeader header;

  /**
   * Always zero.
   */
  uint32_t reserved GNUNET_PACKED;

  /**
   * Identity of the connecting peer.
   */
  struct GNUNET_PeerIdentity peer;

  /**
   * Class of the connecting peer
   * TODO is it correct to send an enum like this?
   */
  enum GNUNET_CORE_PeerClass peer_class;
};


/**
 * Message sent by the service to clients to notify them
 * about a peer disconnecting.
 */
struct DisconnectNotifyMessage
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT.
   */
  struct GNUNET_MessageHeader header;

  /**
   * Always zero.
   */
  uint32_t reserved GNUNET_PACKED;

  /**
   * Identity of the connecting peer.
   */
  struct GNUNET_PeerIdentity peer;
};


/**
 * Message sent by the service to clients to notify them about
 * messages being received or transmitted.  This overall message is
 * followed by the real message, or just the header of the real
 * message (depending on the client's preferences).  The receiver can
 * tell if it got the full message or only a partial message by
 * looking at the size field in the header of NotifyTrafficMessage and
 * checking it with the size field in the message that follows.
 */
struct NotifyTrafficMessage
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND
   * or #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND.
   */
  struct GNUNET_MessageHeader header;

  /**
   * Identity of the receiver or sender.
   */
  struct GNUNET_PeerIdentity peer;

  /* Followed by payload (message or just header), variable size */
};


/**
 * Client notifying core about the maximum-priority
 * message it has in the queue for a particular target.
 */
struct SendMessageRequest
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
   */
  struct GNUNET_MessageHeader header;

  /**
   * How important is this message?
   */
  uint32_t priority GNUNET_PACKED;

  /**
   * By what time would the sender really like to see this
   * message transmitted?
   */
  struct GNUNET_TIME_AbsoluteNBO deadline;

  /**
   * Identity of the intended target.
   */
  struct GNUNET_PeerIdentity peer;

  /**
   * Always zero.
   */
  uint32_t reserved GNUNET_PACKED;

  /**
   * How large is the message?
   */
  uint16_t size GNUNET_PACKED;

  /**
   * Counter for this peer to match SMRs to replies.
   */
  uint16_t smr_id GNUNET_PACKED;
};


/**
 * Core notifying client that it is allowed to now
 * transmit a message to the given target
 * (response to #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST).
 */
struct SendMessageReady
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND_READY
   */
  struct GNUNET_MessageHeader header;

  /**
   * How many bytes are allowed for transmission?
   * Guaranteed to be at least as big as the requested size,
   * or ZERO if the request is rejected (will timeout,
   * peer disconnected, queue full, etc.).
   */
  uint16_t size GNUNET_PACKED;

  /**
   * smr_id from the request.
   */
  uint16_t smr_id GNUNET_PACKED;

  /**
   * Identity of the intended target.
   */
  struct GNUNET_PeerIdentity peer;
};


/**
 * Client asking core to transmit a particular message to a particular
 * target (response to #GNUNET_MESSAGE_TYPE_CORE_SEND_READY).
 */
struct SendMessage
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND
   */
  struct GNUNET_MessageHeader header;

  /**
   * How important is this message? Contains a
   * `enum GNUNET_MQ_PriorityPreferences` in NBO.
   */
  uint32_t priority GNUNET_PACKED;

  /**
   * By what time would the sender really like to see this
   * message transmitted?
   */
  struct GNUNET_TIME_AbsoluteNBO deadline;

  /**
   * Identity of the intended receiver.
   */
  struct GNUNET_PeerIdentity peer;
};


/**
 * Message sent by the service to monitor clients to notify them
 * about a peer changing status.
 */
struct MonitorNotifyMessage
{
  /**
   * Header with type #GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY
   */
  struct GNUNET_MessageHeader header;

  /**
   * New peer state, an `enum GNUNET_CORE_KxState` in NBO.
   */
  uint32_t state GNUNET_PACKED;

  /**
   * Identity of the peer.
   */
  struct GNUNET_PeerIdentity peer;

  /**
   * How long will we stay in this state (if nothing else happens)?
   */
  struct GNUNET_TIME_AbsoluteNBO timeout;
};


GNUNET_NETWORK_STRUCT_END
#endif
/* end of core.h */
