<commit_before>/*
 * Copyright (c) 2009-2010 <NAME>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "maki.h"

#include "network.h"

#include "ilib.h"

#ifdef HAVE_NICE
#include <interfaces.h>
#include <stun/usages/bind.h>
#endif

#ifdef HAVE_GUPNP_IGD_1_0
#include <libgupnp-igd/gupnp-simple-igd.h>
#endif

struct maki_network
{
	makiInstance* instance;

	struct
	{
		gchar* ip;
	}
	local;

	struct
	{
		struct sockaddr_storage addr;
		socklen_t addrlen;
	}
	remote;

	GMutex* lock;

#ifdef HAVE_GUPNP_IGD_1_0
	GUPnPSimpleIgd* upnp_igd;
#endif
};

static gboolean maki_network_update_local (gpointer data)
{
	makiNetwork* net = data;

	g_mutex_lock(net->lock);
	g_free(net->local.ip);
	net->local.ip = NULL;
	g_mutex_unlock(net->lock);

#ifdef HAVE_NICE
	{
		GList* ips;

		if ((ips = nice_interfaces_get_local_ips(FALSE)) != NULL)
		{
			GList* l;

			g_mutex_lock(net->lock);
			net->local.ip = g_strdup(ips->data);
			g_mutex_unlock(net->lock);

			for (l = ips; l != NULL; l = g_list_next(l))
			{
				g_free(l->data);
			}

			g_list_free(ips);
		}
	}
#endif

	return FALSE;
}

static gboolean maki_network_update_remote (gpointer data)
{
	makiNetwork* net = data;

	g_mutex_lock(net->lock);
	memset(&net->remote.addr, 0, sizeof(net->remote.addr));
	net->remote.addrlen = 0;
	g_mutex_unlock(net->lock);

#ifdef HAVE_NICE
	{
		gchar* stun;

		struct addrinfo* ai;
		struct addrinfo* p;
		struct addrinfo hints;

		stun = maki_instance_config_get_string(net->instance, "network", "stun");

		if (stun == NULL)
		{
			goto end;
		}

		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_protocol = 0;
		hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;

		if (getaddrinfo(stun, "3478", NULL, &ai) != 0)
		{
			g_free(stun);
			goto end;
		}

		g_free(stun);

		for (p = ai; p != NULL; p = p->ai_next)
		{
			struct sockaddr_storage me;
			socklen_t me_len = sizeof(me);

			if (stun_usage_bind_run(p->ai_addr, p->ai_addrlen, (struct sockaddr*)&me, &me_len) != STUN_USAGE_BIND_RETURN_SUCCESS)
			{
				continue;
			}

			g_mutex_lock(net->lock);
			net->remote.addr = me;
			net->remote.addrlen = me_len;
			g_mutex_unlock(net->lock);

			break;
		}

		freeaddrinfo(ai);
	}
#endif

end:
	return FALSE;
}

makiNetwork* maki_network_new (makiInstance* inst)
{
	makiNetwork* net;

	net = g_new(makiNetwork, 1);

	net->instance = inst;

	net->local.ip = NULL;

	memset(&net->remote.addr, 0, sizeof(net->remote.addr));
	net->remote.addrlen = 0;

	net->lock = g_mutex_new();

#ifdef HAVE_GUPNP_IGD_1_0
	net->upnp_igd = gupnp_simple_igd_new(NULL);
#endif

	maki_network_update(net);

	return net;
}

void maki_network_free (makiNetwork* net)
{
#ifdef HAVE_GUPNP_IGD_1_0
	g_object_unref(net->upnp_igd);
#endif

	g_mutex_free(net->lock);

	g_free(net->local.ip);

	g_free(net);
}

void maki_network_update (makiNetwork* net)
{
	g_return_if_fail(net != NULL);

	i_idle_add(maki_network_update_local, net, maki_instance_main_context(net->instance));
	i_idle_add(maki_network_update_remote, net, maki_instance_main_context(net->instance));
}
<commit_msg>Do lazy initialization of makiNetwork.<commit_after>/*
 * Copyright (c) 2009-2010 <NAME>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "maki.h"

#include "network.h"

#include "ilib.h"

#ifdef HAVE_NICE
#include <interfaces.h>
#include <stun/usages/bind.h>
#endif

#ifdef HAVE_GUPNP_IGD_1_0
#include <libgupnp-igd/gupnp-simple-igd.h>
#endif

struct maki_network
{
	makiInstance* instance;

	struct
	{
		gchar* ip;
	}
	local;

	struct
	{
		struct sockaddr_storage addr;
		socklen_t addrlen;
	}
	remote;

	GMutex* lock;

#ifdef HAVE_GUPNP_IGD_1_0
	GUPnPSimpleIgd* upnp_igd;
#endif
};

static gboolean maki_network_update_local (gpointer data)
{
	makiNetwork* net = data;

	g_mutex_lock(net->lock);
	g_free(net->local.ip);
	net->local.ip = NULL;
	g_mutex_unlock(net->lock);

#ifdef HAVE_NICE
	{
		GList* ips;

		if ((ips = nice_interfaces_get_local_ips(FALSE)) != NULL)
		{
			GList* l;

			g_mutex_lock(net->lock);
			net->local.ip = g_strdup(ips->data);
			g_mutex_unlock(net->lock);

			for (l = ips; l != NULL; l = g_list_next(l))
			{
				g_free(l->data);
			}

			g_list_free(ips);
		}
	}
#endif

	return FALSE;
}

static gboolean maki_network_update_remote (gpointer data)
{
	makiNetwork* net = data;

	g_mutex_lock(net->lock);
	memset(&net->remote.addr, 0, sizeof(net->remote.addr));
	net->remote.addrlen = 0;
	g_mutex_unlock(net->lock);

#ifdef HAVE_NICE
	{
		gchar* stun;

		struct addrinfo* ai;
		struct addrinfo* p;
		struct addrinfo hints;

		stun = maki_instance_config_get_string(net->instance, "network", "stun");

		if (stun == NULL)
		{
			goto end;
		}

		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_protocol = 0;
		hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;

		if (getaddrinfo(stun, "3478", NULL, &ai) != 0)
		{
			g_free(stun);
			goto end;
		}

		g_free(stun);

		for (p = ai; p != NULL; p = p->ai_next)
		{
			struct sockaddr_storage me;
			socklen_t me_len = sizeof(me);

			if (stun_usage_bind_run(p->ai_addr, p->ai_addrlen, (struct sockaddr*)&me, &me_len) != STUN_USAGE_BIND_RETURN_SUCCESS)
			{
				continue;
			}

			g_mutex_lock(net->lock);
			net->remote.addr = me;
			net->remote.addrlen = me_len;
			g_mutex_unlock(net->lock);

			break;
		}

		freeaddrinfo(ai);
	}
#endif

end:
	return FALSE;
}

makiNetwork* maki_network_new (makiInstance* inst)
{
	makiNetwork* net;

	net = g_new(makiNetwork, 1);

	net->instance = inst;

	net->local.ip = NULL;

	memset(&net->remote.addr, 0, sizeof(net->remote.addr));
	net->remote.addrlen = 0;

	net->lock = g_mutex_new();

#ifdef HAVE_GUPNP_IGD_1_0
	net->upnp_igd = gupnp_simple_igd_new(NULL);
#endif

	return net;
}

void maki_network_free (makiNetwork* net)
{
#ifdef HAVE_GUPNP_IGD_1_0
	g_object_unref(net->upnp_igd);
#endif

	g_mutex_free(net->lock);

	g_free(net->local.ip);

	g_free(net);
}

void maki_network_update (makiNetwork* net)
{
	g_return_if_fail(net != NULL);

	i_idle_add(maki_network_update_local, net, maki_instance_main_context(net->instance));
	i_idle_add(maki_network_update_remote, net, maki_instance_main_context(net->instance));
}

{'fraction_non_alphanumeric': 0.11447503713012681, 'fraction_numerical': 0.007083285730606649, 'mean_word_length': 4.270319084888621, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5169552', 'n_tokens_mistral': 3539, 'n_tokens_neox': 3203, 'n_words': 829}