/*
 * libwebsockets - small server side websockets and web server implementation
 *
 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include <libwebsockets.h>
#include "private-lib-core.h"

/* requires context->lock */
static void
__lws_peer_remove_from_peer_wait_list(struct lws_context *context,
				      struct lws_peer *peer)
{
	struct lws_peer *df;

	lws_start_foreach_llp(struct lws_peer **, p, context->peer_wait_list) {
		if (*p == peer) {
			df = *p;

			*p = df->peer_wait_list;
			df->peer_wait_list = NULL;

			return;
		}
	} lws_end_foreach_llp(p, peer_wait_list);
}

/* requires context->lock */
static void
__lws_peer_add_to_peer_wait_list(struct lws_context *context,
				 struct lws_peer *peer)
{
	__lws_peer_remove_from_peer_wait_list(context, peer);

	peer->peer_wait_list = context->peer_wait_list;
	context->peer_wait_list = peer;
}


struct lws_peer *
lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd)
{
	struct lws_context *context = vhost->context;
	socklen_t rlen = 0;
	void *q;
	uint8_t *q8;
	struct lws_peer *peer;
	uint32_t hash = 0;
	int n, af = AF_INET;
	struct sockaddr_storage addr;

	if (vhost->options & LWS_SERVER_OPTION_UNIX_SOCK)
		return NULL;

#ifdef LWS_WITH_IPV6
	if (LWS_IPV6_ENABLED(vhost)) {
		af = AF_INET6;
	}
#endif
	rlen = sizeof(addr);
	if (getpeername(sockfd, (struct sockaddr*)&addr, &rlen))
		/* eg, udp doesn't have to have a peer */
		return NULL;

#ifdef LWS_WITH_IPV6
	if (af == AF_INET)
#endif
	{
		struct sockaddr_in *s = (struct sockaddr_in *)&addr;
		q = &s->sin_addr;
		rlen = sizeof(s->sin_addr);
	}
#ifdef LWS_WITH_IPV6
	else {
		struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
		q = &s->sin6_addr;
		rlen = sizeof(s->sin6_addr);
	}
#endif

	q8 = q;
	for (n = 0; n < (int)rlen; n++)
		hash = (((hash << 4) | (hash >> 28)) * n) ^ q8[n];

	hash = hash % context->pl_hash_elements;

	lws_context_lock(context, "peer search"); /* <======================= */

	lws_start_foreach_ll(struct lws_peer *, peerx,
			     context->pl_hash_table[hash]) {
		if (peerx->af == af && !memcmp(q, peerx->addr, rlen)) {
			lws_context_unlock(context); /* === */
			return peerx;
		}
	} lws_end_foreach_ll(peerx, next);

	lwsl_info("%s: creating new peer\n", __func__);

	peer = lws_zalloc(sizeof(*peer), "peer");
	if (!peer) {
		lws_context_unlock(context); /* === */
		lwsl_err("%s: OOM for new peer\n", __func__);
		return NULL;
	}

	context->count_peers++;
	peer->next = context->pl_hash_table[hash];
	peer->hash = hash;
	peer->af = af;
	context->pl_hash_table[hash] = peer;
	memcpy(peer->addr, q, rlen);
	time(&peer->time_created);
	/*
	 * On creation, the peer has no wsi attached, so is created on the
	 * wait list.  When a wsi is added it is removed from the wait list.
	 */
	time(&peer->time_closed_all);
	__lws_peer_add_to_peer_wait_list(context, peer);

	lws_context_unlock(context); /* ====================================> */

	return peer;
}

/* requires context->lock */
static int
__lws_peer_destroy(struct lws_context *context, struct lws_peer *peer)
{
	lws_start_foreach_llp(struct lws_peer **, p,
			      context->pl_hash_table[peer->hash]) {
		if (*p == peer) {
			struct lws_peer *df = *p;
			*p = df->next;
			lws_free(df);
			context->count_peers--;

			return 0;
		}
	} lws_end_foreach_llp(p, next);

	return 1;
}

void
lws_peer_cull_peer_wait_list(struct lws_context *context)
{
	struct lws_peer *df;
	time_t t;

	time(&t);

	if (context->next_cull && t < context->next_cull)
		return;

	lws_context_lock(context, "peer cull"); /* <========================= */

	context->next_cull = t + 5;

	lws_start_foreach_llp(struct lws_peer **, p, context->peer_wait_list) {
		if (t - (*p)->time_closed_all > 10) {
			df = *p;

			/* remove us from the peer wait list */
			*p = df->peer_wait_list;
			df->peer_wait_list = NULL;

			__lws_peer_destroy(context, df);
			continue; /* we already point to next, if any */
		}
	} lws_end_foreach_llp(p, peer_wait_list);

	lws_context_unlock(context); /* ====================================> */
}

void
lws_peer_add_wsi(struct lws_context *context, struct lws_peer *peer,
		 struct lws *wsi)
{
	if (!peer)
		return;

	lws_context_lock(context, "peer add"); /* <========================== */

	peer->count_wsi++;
	wsi->peer = peer;
	__lws_peer_remove_from_peer_wait_list(context, peer);

	lws_context_unlock(context); /* ====================================> */
}

void
lws_peer_dump_from_wsi(struct lws *wsi)
{
	struct lws_peer *peer;

	if (!wsi || !wsi->peer)
		return;

	peer = wsi->peer;

#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
	lwsl_notice("%s: wsi %p: created %llu: wsi: %d/%d, ah %d/%d\n",
			__func__,
			wsi, (unsigned long long)peer->time_created,
			peer->count_wsi, peer->total_wsi,
			peer->http.count_ah, peer->http.total_ah);
#else
	lwsl_notice("%s: wsi %p: created %llu: wsi: %d/%d\n", __func__,
			wsi, (unsigned long long)peer->time_created,
			peer->count_wsi, peer->total_wsi);
#endif
}

void
lws_peer_track_wsi_close(struct lws_context *context, struct lws_peer *peer)
{
	if (!peer)
		return;

	lws_context_lock(context, "peer wsi close"); /* <==================== */

	assert(peer->count_wsi);
	peer->count_wsi--;

	if (!peer->count_wsi
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
			&& !peer->http.count_ah
#endif
	) {
		/*
		 * in order that we can accumulate peer activity correctly
		 * allowing for periods when the peer has no connections,
		 * we don't synchronously destroy the peer when his last
		 * wsi closes.  Instead we mark the time his last wsi
		 * closed and add him to a peer_wait_list to be reaped
		 * later if no further activity is coming.
		 */
		time(&peer->time_closed_all);
		__lws_peer_add_to_peer_wait_list(context, peer);
	}

	lws_context_unlock(context); /* ====================================> */
}

#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
int
lws_peer_confirm_ah_attach_ok(struct lws_context *context,
			      struct lws_peer *peer)
{
	if (!peer)
		return 0;

	if (context->ip_limit_ah &&
	    peer->http.count_ah >= context->ip_limit_ah) {
		lwsl_info("peer reached ah limit %d, deferring\n",
				context->ip_limit_ah);

		return 1;
	}

	return 0;
}

void
lws_peer_track_ah_detach(struct lws_context *context, struct lws_peer *peer)
{
	if (!peer)
		return;

	lws_context_lock(context, "peer ah detach"); /* <==================== */
	assert(peer->http.count_ah);
	peer->http.count_ah--;
	lws_context_unlock(context); /* ====================================> */
}
#endif
