/* 3GPP TS 29.244 PFCP Node
 * (C) 2021-2025 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * All Rights Reserved.
 *
 * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de>
 *
 * SPDX-License-Identifier: GPL-2.0+
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include <osmocom/core/linuxlist.h>
#include <osmocom/core/hashtable.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/use_count.h>

#include <osmocom/pfcp/pfcp_msg.h>

struct pfcp_node_peer {
	/* item in up_endpoint->pfcp_node_peer_list */
	struct llist_head entry;

	/* list of struct pfcp_entity_peer. */
	struct llist_head entity_list;

	struct osmo_fsm_inst *fi;
	/* backpointer */
	struct up_endpoint *up_endpoint;

	/* peer's remote address */
	struct osmo_pfcp_ie_node_id node_id;

	struct osmo_pfcp_ie_up_function_features local_up_features;
	struct osmo_pfcp_ie_cp_function_features peer_cp_features;

	struct osmo_use_count use_count;
	struct osmo_use_count_entry use_count_buf[5];
};

struct pfcp_node_peer *pfcp_node_peer_alloc(struct up_endpoint *up_endpoint, const struct osmo_pfcp_ie_node_id *node_id);
void pfcp_node_peer_free(struct pfcp_node_peer *peer);

struct pfcp_entity_peer *pfcp_node_peer_find_entity_by_remote_addr(struct pfcp_node_peer *peer, const struct osmo_sockaddr *remote_addr);
char *pfcp_node_peer_node_id_str(struct pfcp_node_peer *node_peer);

#define pfcp_node_peer_get(PFCP_NODE_PEER, USE) OSMO_ASSERT(osmo_use_count_get_put(&(PFCP_NODE_PEER)->use_count, USE, 1) == 0)
#define pfcp_node_peer_put(PFCP_NODE_PEER, USE) OSMO_ASSERT(osmo_use_count_get_put(&(PFCP_NODE_PEER)->use_count, USE, -1) == 0)

#define LOG_PNP(PFCP_NODE_PEER, LEVEL, FMT, ARGS...) \
	LOGP(DGTP, LEVEL, "pfcp_node_peer(%s): " FMT, pfcp_node_peer_node_id_str(PFCP_NODE_PEER), ##ARGS)
