summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/gsm_subscriber.h14
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c50
-rw-r--r--openbsc/src/libmsc/gsm_subscriber.c14
3 files changed, 59 insertions, 19 deletions
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 88c36e7..151f3dd 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -88,6 +88,20 @@ enum gsm_subscriber_update_reason {
GSM_SUBSCRIBER_UPDATE_EQUIPMENT,
};
+/*
+ * Struct for pending channel requests. This is managed in the
+ * llist_head requests of each subscriber. The reference counting
+ * should work in such a way that a subscriber with a pending request
+ * remains in memory.
+ */
+struct subscr_request {
+ struct llist_head entry;
+
+ /* the callback data */
+ gsm_cbfn *cbfn;
+ void *param;
+};
+
struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr);
struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr);
struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp,
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 897f972..cccb8f7 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -1245,6 +1245,47 @@ static int gsm0408_rcv_mm(struct gsm_subscriber_connection *conn, struct msgb *m
return rc;
}
+static int handle_paging_resp(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, struct gsm_subscriber *subscr)
+{
+ struct subscr_request *req, *req2;
+
+ if (!conn->subscr) {
+ conn->subscr = subscr;
+ } else if (conn->subscr != subscr) {
+ LOGP(DRR, LOGL_ERROR, "<- Channel already owned by someone else?\n");
+ subscr_put(subscr);
+ return -EINVAL;
+ } else {
+ DEBUGP(DRR, "<- Channel already owned by us\n");
+ subscr_put(subscr);
+ subscr = conn->subscr;
+ }
+
+ osmo_counter_inc(conn->network->stats.paging.completed);
+
+ if (!subscr->is_paging) {
+ LOGP(DRR, LOGL_ERROR, "Paging Response received for subscriber that is not paging\n");
+ return -1;
+ }
+
+ llist_for_each_entry_safe(req, req2, &subscr->requests, entry) {
+ gsm_cbfn *cbfn = req->cbfn;
+ void *param = req->param;
+
+ llist_del(&req->entry);
+ req = NULL;
+
+ if (conn && cbfn) {
+ LOGP(DPAG, LOGL_DEBUG, "Calling paging cbfn.\n");
+ cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_SUCCEEDED,
+ msg, conn, param);
+ } else
+ LOGP(DPAG, LOGL_DEBUG, "Paging without action.\n");
+ }
+ return 0;
+}
+
/* Receive a PAGING RESPONSE message from the MS */
static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
@@ -1254,7 +1295,6 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m
uint8_t mi_type;
char mi_string[GSM48_MI_SIZE];
struct gsm_subscriber *subscr = NULL;
- int rc = 0;
resp = (struct gsm48_pag_resp *) &gh->data[0];
gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
@@ -1289,12 +1329,12 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m
/* We received a paging */
conn->expire_timer_stopped = 1;
+ /* FIXME start Integrity Protection in Iu mode */
+
#if BEFORE_MSCSPLIT
- rc = gsm48_handle_paging_resp(conn, msg, subscr);
- return rc;
+ return gsm48_handle_paging_resp(conn, msg, subscr);
#else
- LOGP(DRR, LOGL_ERROR, "MSC wants to tell BSC to gsm48_handle_paging_resp() but A-interface not implemented\n");
- return -1;
+ return handle_paging_resp(conn, msg, subscr);
#endif
}
diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c
index 2fd9932..cb9303c 100644
--- a/openbsc/src/libmsc/gsm_subscriber.c
+++ b/openbsc/src/libmsc/gsm_subscriber.c
@@ -48,20 +48,6 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
gsm_cbfn *cb, void *cb_data);
-/*
- * Struct for pending channel requests. This is managed in the
- * llist_head requests of each subscriber. The reference counting
- * should work in such a way that a subscriber with a pending request
- * remains in memory.
- */
-struct subscr_request {
- struct llist_head entry;
-
- /* the callback data */
- gsm_cbfn *cbfn;
- void *param;
-};
-
static struct gsm_subscriber *get_subscriber(struct gsm_subscriber_group *sgrp,
int type, const char *ident)
{