/*
 * Copyright (c) 2006 Georgia Tech Research Corporation
 *               2007 INRIA
 *
 * SPDX-License-Identifier: GPL-2.0-only
 *
 * Authors: George F. Riley<riley@ece.gatech.edu>
 *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
 */

#ifndef UDP_SOCKET_H
#define UDP_SOCKET_H

#include "ns3/callback.h"
#include "ns3/object.h"
#include "ns3/ptr.h"
#include "ns3/socket.h"
#include "ns3/traced-callback.h"

namespace ns3
{

class Node;
class Packet;

/**
 * @ingroup socket
 * @ingroup udp
 *
 * @brief (abstract) base class of all UdpSockets
 *
 * This class exists solely for hosting UdpSocket attributes that can
 * be reused across different implementations, and for declaring
 * UDP-specific multicast API.
 */
class UdpSocket : public Socket
{
  public:
    /**
     * Get the type ID.
     * @brief Get the type ID.
     * @return the object TypeId
     */
    static TypeId GetTypeId();

    UdpSocket();
    ~UdpSocket() override;

    /**
     * @brief Corresponds to socket option MCAST_JOIN_GROUP
     *
     * @param interface interface number, or 0
     * @param groupAddress multicast group address
     * @returns on success, zero is returned.  On error, -1 is returned,
     *          and errno is set appropriately
     *
     * Enable reception of multicast datagrams for this socket on the
     * interface number specified.  If zero is specified as
     * the interface, then a single local interface is chosen by
     * system.  In the future, this function will generate trigger IGMP
     * joins as necessary when IGMP is implemented, but for now, this
     * just enables multicast datagram reception in the system if not already
     * enabled for this interface/groupAddress combination.
     *
     * @attention IGMP is not yet implemented in ns-3
     *
     * This function may be called repeatedly on a given socket but each
     * join must be for a different multicast address, or for the same
     * multicast address but on a different interface from previous joins.
     * This enables host multihoming, and the ability to join the same
     * group on different interfaces.
     */
    virtual int MulticastJoinGroup(uint32_t interface, const Address& groupAddress) = 0;

    /**
     * @brief Corresponds to socket option MCAST_LEAVE_GROUP
     *
     * @param interface interface number, or 0
     * @param groupAddress multicast group address
     * @returns on success, zero is returned.  On error, -1 is returned,
     *          and errno is set appropriately
     *
     * Disable reception of multicast datagrams for this socket on the
     * interface number specified.  If zero is specified as
     * the interfaceIndex, then a single local interface is chosen by
     * system.  In the future, this function will generate trigger IGMP
     * leaves as necessary when IGMP is implemented, but for now, this
     * just disables multicast datagram reception in the system if this
     * socket is the last for this interface/groupAddress combination.
     *
     * @attention IGMP is not yet implemented in ns-3
     */
    virtual int MulticastLeaveGroup(uint32_t interface, const Address& groupAddress) = 0;

  private:
    // Indirect the attribute setting and getting through private virtual methods
    /**
     * @brief Set the receiving buffer size
     * @param size the buffer size
     */
    virtual void SetRcvBufSize(uint32_t size) = 0;
    /**
     * @brief Get the receiving buffer size
     * @returns the buffer size
     */
    virtual uint32_t GetRcvBufSize() const = 0;
    /**
     * @brief Set the IP multicast TTL
     * @param ipTtl the IP multicast TTL
     */
    virtual void SetIpMulticastTtl(uint8_t ipTtl) = 0;
    /**
     * @brief Get the IP multicast TTL
     * @returns the IP multicast TTL
     */
    virtual uint8_t GetIpMulticastTtl() const = 0;
    /**
     * @brief Set the IP multicast interface
     * @param ipIf the IP multicast interface
     */
    virtual void SetIpMulticastIf(int32_t ipIf) = 0;
    /**
     * @brief Get the IP multicast interface
     * @returns the IP multicast interface
     */
    virtual int32_t GetIpMulticastIf() const = 0;
    /**
     * @brief Set the IP multicast loop capability
     *
     * This means that the socket will receive the packets
     * sent by itself on a multicast address.
     * Equivalent to setsockopt  IP_MULTICAST_LOOP
     *
     * @param loop the IP multicast loop capability
     */
    virtual void SetIpMulticastLoop(bool loop) = 0;
    /**
     * @brief Get the IP multicast loop capability
     *
     * This means that the socket will receive the packets
     * sent by itself on a multicast address.
     * Equivalent to setsockopt  IP_MULTICAST_LOOP
     *
     * @returns the IP multicast loop capability
     */
    virtual bool GetIpMulticastLoop() const = 0;
    /**
     * @brief Set the MTU discover capability
     *
     * @param discover the MTU discover capability
     */
    virtual void SetMtuDiscover(bool discover) = 0;
    /**
     * @brief Get the MTU discover capability
     *
     * @returns the MTU discover capability
     */
    virtual bool GetMtuDiscover() const = 0;
};

} // namespace ns3

#endif /* UDP_SOCKET_H */
