# HG changeset patch
# Node ID 3f59da5156297400ec64977e5568dc6f435b699a
# Parent  5d4c49a1b71a206fb56705d56c594e86a05f97e6
diff --git a/hiya/hiyaendpoint.c b/hiya/hiyaendpoint.c
new file mode 100644
--- /dev/null
+++ b/hiya/hiyaendpoint.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2025 Hiya Developers
+ *
+ * Hiya is the legal property of its developers, whose names are too
+ * numerous to list here. Please refer to the AUTHORS file distributed
+ * with this source distribution
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "hiyaendpoint.h"
+
+struct _HiyaEndpoint {
+	GInetSocketAddress parent;
+
+	HiyaTxt *txt;
+};
+
+enum {
+	PROP_0,
+	PROP_TXT,
+	N_PROPERTIES,
+};
+static GParamSpec *properties[N_PROPERTIES] = {NULL, };
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+hiya_endpoint_set_txt(HiyaEndpoint *endpoint, HiyaTxt *txt) {
+	g_return_if_fail(HIYA_IS_ENDPOINT(endpoint));
+
+	if(g_set_object(&endpoint->txt, txt)) {
+		g_object_notify_by_pspec(G_OBJECT(endpoint), properties[PROP_TXT]);
+	}
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_FINAL_TYPE(HiyaEndpoint, hiya_endpoint, G_TYPE_INET_SOCKET_ADDRESS)
+
+static void
+hiya_endpoint_finalize(GObject *obj) {
+	HiyaEndpoint *endpoint = HIYA_ENDPOINT(obj);
+
+	g_clear_object(&endpoint->txt);
+
+	G_OBJECT_CLASS(hiya_endpoint_parent_class)->finalize(obj);
+}
+
+static void
+hiya_endpoint_get_property(GObject *obj, guint param_id, GValue *value,
+                           GParamSpec *pspec)
+{
+	HiyaEndpoint *endpoint = HIYA_ENDPOINT(obj);
+
+	switch(param_id) {
+	case PROP_TXT:
+		g_value_set_object(value, hiya_endpoint_get_txt(endpoint));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+		break;
+	}
+}
+
+static void
+hiya_endpoint_set_property(GObject *obj, guint param_id, const GValue *value,
+                           GParamSpec *pspec)
+{
+	HiyaEndpoint *endpoint = HIYA_ENDPOINT(obj);
+
+	switch(param_id) {
+	case PROP_TXT:
+		hiya_endpoint_set_txt(endpoint, g_value_get_object(value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+		break;
+	}
+}
+
+static void
+hiya_endpoint_init(HiyaEndpoint *endpoint) {
+	endpoint->txt = hiya_txt_new();
+}
+
+static void
+hiya_endpoint_class_init(HiyaEndpointClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	obj_class->finalize = hiya_endpoint_finalize;
+	obj_class->get_property = hiya_endpoint_get_property;
+	obj_class->set_property = hiya_endpoint_set_property;
+
+	/**
+	 * HiyaEndpoint:txt:
+	 *
+	 * The TXT record for the endpoint.
+	 *
+	 * Since: 0.1
+	 */
+	properties[PROP_TXT] = g_param_spec_object(
+		"txt", NULL, NULL,
+		HIYA_TYPE_TXT,
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+HiyaTxt *
+hiya_endpoint_get_txt(HiyaEndpoint *endpoint) {
+	g_return_val_if_fail(HIYA_IS_ENDPOINT(endpoint), NULL);
+
+	return endpoint->txt;
+}
+
+GSocketAddress *
+hiya_endpoint_new(GInetAddress *address, guint16 port, HiyaTxt *txt) {
+	g_return_val_if_fail(G_IS_INET_ADDRESS(address), NULL);
+	g_return_val_if_fail(HIYA_IS_TXT(txt), NULL);
+
+	return g_object_new(
+		HIYA_TYPE_ENDPOINT,
+		"address", address,
+		"port", port,
+		"txt", txt,
+		NULL);
+}
diff --git a/hiya/hiyaendpoint.h b/hiya/hiyaendpoint.h
new file mode 100644
--- /dev/null
+++ b/hiya/hiyaendpoint.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2025 Hiya Developers
+ *
+ * Hiya is the legal property of its developers, whose names are too
+ * numerous to list here. Please refer to the AUTHORS file distributed
+ * with this source distribution
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef HIYA_ENDPOINT_H
+#define HIYA_ENDPOINT_H
+
+#include <glib.h>
+
+#include <gio/gio.h>
+
+#include "hiyatxt.h"
+#include "hiyaversion.h"
+
+G_BEGIN_DECLS
+
+#define HIYA_TYPE_ENDPOINT (hiya_endpoint_get_type())
+
+/**
+ * HiyaEndpoint:
+ *
+ * A data store for service endpoints.
+ *
+ * Since: 0.1
+ */
+HIYA_AVAILABLE_IN_0_1
+G_DECLARE_FINAL_TYPE(HiyaEndpoint, hiya_endpoint, HIYA, ENDPOINT, GInetSocketAddress)
+
+/**
+ * hiya_endpoint_get_txt:
+ *
+ * Gets the TXT record.
+ *
+ * Returns: (transfer none): The TXT record.
+ *
+ * Since: 0.1
+ */
+HIYA_AVAILABLE_IN_0_1
+HiyaTxt *hiya_endpoint_get_txt(HiyaEndpoint *endpoint);
+
+/**
+ * hiya_endpoint_new:
+ * @address: the addres of the endpoint
+ * @port: the port of the endpoint
+ * @txt: the TXT record
+ *
+ * Creates a new end_point instance.
+ *
+ * Returns: (transfer full) (type HiyaEndpoint): The new instance.
+ *
+ * Since: 0.1
+ */
+HIYA_AVAILABLE_IN_0_1
+GSocketAddress *hiya_endpoint_new(GInetAddress *address, guint16 port, HiyaTxt *txt);
+
+G_END_DECLS
+
+#endif /* HIYA_ENDPOINT_H */
diff --git a/hiya/meson.build b/hiya/meson.build
--- a/hiya/meson.build
+++ b/hiya/meson.build
@@ -1,11 +1,13 @@
 HIYA_LIBRARY_VERSION = '0.1.0'
 
 HIYA_SOURCES = [
+  'hiyaendpoint.c',
   'hiyatxt.c',
   'hiyaversion.c',
 ]
 
 HIYA_HEADERS = [
+  'hiyaendpoint.h',
   'hiyatxt.h',
   'hiyaversion.h',
 ]
diff --git a/hiya/tests/meson.build b/hiya/tests/meson.build
--- a/hiya/tests/meson.build
+++ b/hiya/tests/meson.build
@@ -1,4 +1,5 @@
 PROGRAMS = [
+  'endpoint',
   'txt',
 ]
 
diff --git a/hiya/tests/test_endpoint.c b/hiya/tests/test_endpoint.c
new file mode 100644
--- /dev/null
+++ b/hiya/tests/test_endpoint.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2025 Hiya Developers
+ *
+ * Hiya is the legal property of its developers, whose names are too
+ * numerous to list here. Please refer to the AUTHORS file distributed
+ * with this source distribution
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <hiya.h>
+
+/******************************************************************************
+ * Tests
+ *****************************************************************************/
+static void
+test_hiya_endpoint_new(void) {
+	HiyaTxt *txt = NULL;
+	GInetAddress *address = NULL;
+	GSocketAddress *endpoint = NULL;
+
+	address = g_inet_address_new_from_string("127.0.0.1");
+	txt = hiya_txt_new();
+	endpoint = hiya_endpoint_new(address, 1337, txt);
+
+	g_assert_true(HIYA_IS_ENDPOINT(endpoint));
+	g_assert_true(G_IS_INET_SOCKET_ADDRESS(endpoint));
+
+	g_assert_finalize_object(endpoint);
+	g_assert_finalize_object(txt);
+	g_assert_finalize_object(address);
+}
+
+static void
+test_hiya_endpoint_properties(void) {
+	HiyaTxt *txt = NULL;
+	HiyaTxt *txt1 = NULL;
+	GInetAddress *address = NULL;
+	GInetAddress *address1 = NULL;
+	GSocketAddress *endpoint = NULL;
+	guint16 port = 1337;
+	/* There is no g_param_spec_unit16, so we need to use an uint when
+	 * retrieving the value.
+	 */
+	guint port1 = 0;
+
+	txt = hiya_txt_new();
+	address = g_inet_address_new_from_string("127.0.0.1");
+
+	endpoint = g_object_new(
+		HIYA_TYPE_ENDPOINT,
+		"address", address,
+		"port", port,
+		"txt", txt,
+		NULL);
+
+	g_assert_true(HIYA_IS_ENDPOINT(endpoint));
+	g_assert_true(G_IS_INET_SOCKET_ADDRESS(endpoint));
+
+	g_object_get(
+		G_OBJECT(endpoint),
+		"address", &address1,
+		"port", &port1,
+		"txt", &txt1,
+		NULL);
+
+	g_assert_true(g_inet_address_equal(address, address1));
+	g_clear_object(&address1);
+
+	g_assert_cmpuint(port, ==, 1337);
+
+	g_assert_true(txt1 == txt);
+	g_clear_object(&txt1);
+
+	g_assert_finalize_object(endpoint);
+	g_assert_finalize_object(txt);
+	g_assert_finalize_object(address);
+}
+
+/******************************************************************************
+ * Main
+ *****************************************************************************/
+int
+main(int argc, char *argv[]) {
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_func("/hiya/endpoint/new", test_hiya_endpoint_new);
+	g_test_add_func("/hiya/endpoint/properties",
+	                test_hiya_endpoint_properties);
+
+	return g_test_run();
+}
+
