introduce ue_context management

We keep one 'ue_context' structure for every UE that we see
a UE REGISTER REQUEST for.
diff --git a/src/hnbgw.c b/src/hnbgw.c
index 2c49c4d..ada3490 100644
--- a/src/hnbgw.c
+++ b/src/hnbgw.c
@@ -26,6 +26,7 @@
 #include "hnbgw_rua.h"
 
 static void *tall_hnb_ctx;
+static void *tall_ue_ctx;
 void *talloc_asn1_ctx;
 
 struct hnb_gw g_hnb_gw = {
@@ -34,6 +35,64 @@
 	},
 };
 
+struct ue_context *ue_context_by_id(uint32_t id)
+{
+	struct ue_context *ue;
+
+	llist_for_each_entry(ue, &g_hnb_gw.ue_list, list) {
+		if (ue->context_id == id)
+			return ue;
+	}
+	return NULL;
+
+}
+
+struct ue_context *ue_context_by_imsi(const char *imsi)
+{
+	struct ue_context *ue;
+
+	llist_for_each_entry(ue, &g_hnb_gw.ue_list, list) {
+		if (!strcmp(ue->imsi, imsi))
+			return ue;
+	}
+	return NULL;
+}
+
+static uint32_t get_next_ue_ctx_id(void)
+{
+	uint32_t id;
+
+	do {
+		id = g_hnb_gw.next_ue_ctx_id++;
+	} while (ue_context_by_id(id));
+
+	return id;
+}
+
+struct ue_context *ue_context_alloc(struct hnb_context *hnb, const char *imsi)
+{
+	struct ue_context *ue;
+
+	ue = talloc_zero(tall_hnb_ctx, struct ue_context);
+	if (!ue)
+		return NULL;
+
+	ue->hnb = hnb;
+	strncpy(ue->imsi, imsi, sizeof(ue->imsi));
+	ue->context_id = get_next_ue_ctx_id();
+	llist_add_tail(&g_hnb_gw.ue_list, &ue->list);
+
+	return ue;
+}
+
+void ue_context_free(struct ue_context *ue)
+{
+	llist_del(&ue->list);
+	talloc_free(ue);
+}
+
+
+
 static int hnb_read_cb(struct osmo_fd *fd)
 {
 	struct hnb_context *hnb = fd->data;
@@ -180,12 +239,14 @@
 	int rc;
 
 	tall_hnb_ctx = talloc_named_const(NULL, 0, "hnb_context");
+	tall_ue_ctx = talloc_named_const(NULL, 0, "ue_context");
 	talloc_asn1_ctx = talloc_named_const(NULL, 0, "asn1_context");
 
 	g_hnb_gw.listen_fd.cb = listen_fd_cb;
 	g_hnb_gw.listen_fd.when = BSC_FD_READ;
 	g_hnb_gw.listen_fd.data = &g_hnb_gw;
 	INIT_LLIST_HEAD(&g_hnb_gw.hnb_list);
+	INIT_LLIST_HEAD(&g_hnb_gw.ue_list);
 
 	rc = osmo_init_logging(&hnbgw_log_info);
 	if (rc < 0)
diff --git a/src/hnbgw.h b/src/hnbgw.h
index 17ce562..e88baa7 100644
--- a/src/hnbgw.h
+++ b/src/hnbgw.h
@@ -60,6 +60,7 @@
 	struct llist_head list;
 	/*! Unique Context ID for this UE */
 	uint32_t context_id;
+	char imsi[16+1];
 	/*! UE is serviced via this HNB */
 	struct hnb_context *hnb;
 };
@@ -76,6 +77,13 @@
 	/*! SCTP listen socket for incoming connections */
 	struct osmo_fd listen_fd;
 	struct llist_head hnb_list;
+	struct llist_head ue_list;
+	uint32_t next_ue_ctx_id;
 };
 
 extern struct hnb_gw g_hnb_gw;
+
+struct ue_context *ue_context_by_id(uint32_t id);
+struct ue_context *ue_context_by_imsi(const char *imsi);
+struct ue_context *ue_context_alloc(struct hnb_context *hnb, const char *imsi);
+void ue_context_free(struct ue_context *ue);
diff --git a/src/hnbgw_hnbap.c b/src/hnbgw_hnbap.c
index cdd4895..d00d59e 100644
--- a/src/hnbgw_hnbap.c
+++ b/src/hnbgw_hnbap.c
@@ -23,6 +23,7 @@
 	return osmo_wqueue_enqueue(&ctx->wqueue, msg);
 }
 
+
 static int hnbgw_tx_hnb_register_acc(struct hnb_context *ctx)
 {
 	HNBRegisterAccept_t accept_out;
@@ -110,11 +111,14 @@
 	if (rc < 0)
 		return rc;
 
+	/* FIXME: convert UE identity into a more palatable format */
+	ue = ue_context_by_imsi("123");
+	if (!ue)
+		ue = ue_context_alloc(ctx, "123");
+
 	DEBUGP(DMAIN, "UE-REGSITER-REQ ID_type=%d cause=%ld\n",
 		ies.uE_Identity.present, ies.registration_Cause);
 
-	/* FIXME: convert UE identity into a more palatable format */
-
 	/* Send UERegisterAccept */
 	return hnbgw_tx_ue_register_acc(ue);
 }