blob: 526ad9235d1f519430b9c9160dd07092fcba833f [file] [log] [blame]
Harald Welteb8b85a12016-06-17 00:06:42 +02001/* MSC subscriber connection implementation */
2
3/*
4 * (C) 2016 by sysmocom s.m.f.c. <info@sysmocom.de>
5 * All Rights Reserved
6 *
7 * Author: Neels Hofmeyr
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <osmocom/core/logging.h>
25#include <osmocom/core/fsm.h>
Harald Welte2483f1b2016-06-19 18:06:02 +020026#include <osmocom/core/signal.h>
Harald Welteb8b85a12016-06-17 00:06:42 +020027
Neels Hofmeyr90843962017-09-04 15:04:35 +020028#include <osmocom/msc/osmo_msc.h>
29#include <osmocom/msc/vlr.h>
30#include <osmocom/msc/debug.h>
31#include <osmocom/msc/transaction.h>
32#include <osmocom/msc/signal.h>
33#include <osmocom/msc/a_iface.h>
Daniel Willmann4e825b62018-02-15 10:33:26 +010034#include <osmocom/msc/iucs.h>
Philipp Maierfbf66102017-04-09 12:32:51 +020035
Harald Welte2483f1b2016-06-19 18:06:02 +020036#define SUBSCR_CONN_TIMEOUT 5 /* seconds */
Harald Welteb8b85a12016-06-17 00:06:42 +020037
38static const struct value_string subscr_conn_fsm_event_names[] = {
39 OSMO_VALUE_STRING(SUBSCR_CONN_E_INVALID),
Harald Welte2483f1b2016-06-19 18:06:02 +020040 OSMO_VALUE_STRING(SUBSCR_CONN_E_START),
Harald Welteb8b85a12016-06-17 00:06:42 +020041 OSMO_VALUE_STRING(SUBSCR_CONN_E_ACCEPTED),
Harald Welte2483f1b2016-06-19 18:06:02 +020042 OSMO_VALUE_STRING(SUBSCR_CONN_E_COMMUNICATING),
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +010043 OSMO_VALUE_STRING(SUBSCR_CONN_E_RELEASE_WHEN_UNUSED),
Harald Welteb8b85a12016-06-17 00:06:42 +020044 OSMO_VALUE_STRING(SUBSCR_CONN_E_MO_CLOSE),
45 OSMO_VALUE_STRING(SUBSCR_CONN_E_CN_CLOSE),
Harald Welteb8b85a12016-06-17 00:06:42 +020046 { 0, NULL }
47};
48
Neels Hofmeyr1ba0df22018-04-02 23:00:00 +020049const struct value_string complete_layer3_type_names[] = {
Harald Welteb8b85a12016-06-17 00:06:42 +020050 OSMO_VALUE_STRING(SUBSCR_CONN_FROM_INVALID),
51 OSMO_VALUE_STRING(SUBSCR_CONN_FROM_LU),
52 OSMO_VALUE_STRING(SUBSCR_CONN_FROM_CM_SERVICE_REQ),
53 OSMO_VALUE_STRING(SUBSCR_CONN_FROM_PAGING_RESP),
54 { 0, NULL }
55};
56
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020057static void paging_event(struct gsm_subscriber_connection *conn,
58 enum gsm_paging_event pe)
Harald Welteb8b85a12016-06-17 00:06:42 +020059{
Harald Welte2483f1b2016-06-19 18:06:02 +020060 subscr_paging_dispatch(GSM_HOOK_RR_PAGING, pe, NULL, conn, conn->vsub);
61}
62
63void subscr_conn_fsm_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
64{
65 OSMO_ASSERT(event == SUBSCR_CONN_E_START);
66 osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_NEW,
67 SUBSCR_CONN_TIMEOUT, 0);
Harald Welteb8b85a12016-06-17 00:06:42 +020068}
69
70void subscr_conn_fsm_new(struct osmo_fsm_inst *fi, uint32_t event, void *data)
71{
72 struct gsm_subscriber_connection *conn = fi->priv;
Neels Hofmeyr1ba0df22018-04-02 23:00:00 +020073 enum complete_layer3_type from = SUBSCR_CONN_FROM_INVALID;
Harald Welte2483f1b2016-06-19 18:06:02 +020074 bool success;
Harald Welteb8b85a12016-06-17 00:06:42 +020075
76 if (data) {
Neels Hofmeyr1ba0df22018-04-02 23:00:00 +020077 from = *(enum complete_layer3_type*)data;
78 LOGPFSM(fi, "%s\n", complete_layer3_type_name(from));
Harald Welteb8b85a12016-06-17 00:06:42 +020079 }
80
81 /* If accepted, transition the state, all other cases mean failure. */
82 switch (event) {
83 case SUBSCR_CONN_E_ACCEPTED:
Harald Welte2483f1b2016-06-19 18:06:02 +020084 osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_ACCEPTED,
85 SUBSCR_CONN_TIMEOUT, 0);
Harald Welteb8b85a12016-06-17 00:06:42 +020086 break;
87
88 case SUBSCR_CONN_E_MO_CLOSE:
89 case SUBSCR_CONN_E_CN_CLOSE:
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020090 if (data)
91 LOGPFSM(fi, "Close event, cause %u\n",
92 *(uint32_t*)data);
93 /* will release further below, see
94 * 'if (fi->state != SUBSCR_CONN_S_ACCEPTED)' */
Harald Welteb8b85a12016-06-17 00:06:42 +020095 break;
96
97 default:
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020098 LOGPFSML(fi, LOGL_ERROR,
99 "Unexpected event: %d %s\n", event,
100 osmo_fsm_event_name(fi->fsm, event));
Harald Welteb8b85a12016-06-17 00:06:42 +0200101 break;
102 }
103
Harald Welte2483f1b2016-06-19 18:06:02 +0200104 success = (fi->state == SUBSCR_CONN_S_ACCEPTED);
105
106 if (from == SUBSCR_CONN_FROM_LU)
107 rate_ctr_inc(&conn->network->msc_ctrs->ctr[
108 success ? MSC_CTR_LOC_UPDATE_COMPLETED
109 : MSC_CTR_LOC_UPDATE_FAILED]);
110
111 /* signal paging success or failure in case this was a paging */
112 if (from == SUBSCR_CONN_FROM_PAGING_RESP)
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200113 paging_event(conn,
114 success ? GSM_PAGING_SUCCEEDED
115 : GSM_PAGING_EXPIRED);
116
117 /* FIXME rate counters */
118 /*rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED]);*/
Harald Welteb8b85a12016-06-17 00:06:42 +0200119
120 /* On failure, discard the conn */
Harald Welte2483f1b2016-06-19 18:06:02 +0200121 if (!success) {
Harald Welteb8b85a12016-06-17 00:06:42 +0200122 /* TODO: on MO_CLOSE or CN_CLOSE, first go to RELEASING and
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200123 * await BSC/RNC confirmation? */
Harald Welteb8b85a12016-06-17 00:06:42 +0200124 osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
125 return;
126 }
127
Harald Welteb8b85a12016-06-17 00:06:42 +0200128 if (from == SUBSCR_CONN_FROM_CM_SERVICE_REQ) {
129 conn->received_cm_service_request = true;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200130 LOGPFSML(fi, LOGL_DEBUG, "received_cm_service_request = true\n");
Harald Welteb8b85a12016-06-17 00:06:42 +0200131 }
132
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100133 osmo_fsm_inst_dispatch(fi, SUBSCR_CONN_E_RELEASE_WHEN_UNUSED, data);
Harald Welteb8b85a12016-06-17 00:06:42 +0200134}
135
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100136static void subscr_conn_fsm_release_when_unused(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Harald Welteb8b85a12016-06-17 00:06:42 +0200137{
138 struct gsm_subscriber_connection *conn = fi->priv;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200139 struct gsm_trans *trans;
Harald Welteb8b85a12016-06-17 00:06:42 +0200140
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200141 if (conn->silent_call) {
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100142 LOGPFSML(fi, LOGL_DEBUG, "%s: silent call still active\n", __func__);
Harald Welteb8b85a12016-06-17 00:06:42 +0200143 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200144 }
Harald Welteb8b85a12016-06-17 00:06:42 +0200145
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200146 if (conn->received_cm_service_request) {
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100147 LOGPFSML(fi, LOGL_DEBUG, "%s: still awaiting first request after a CM Service Request\n",
148 __func__);
Harald Welteb8b85a12016-06-17 00:06:42 +0200149 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200150 }
Harald Welteb8b85a12016-06-17 00:06:42 +0200151
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200152 if (conn->vsub && !llist_empty(&conn->vsub->cs.requests)) {
153 struct subscr_request *sr;
154 if (!log_check_level(fi->fsm->log_subsys, LOGL_DEBUG)) {
155 llist_for_each_entry(sr, &conn->vsub->cs.requests, entry) {
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100156 LOGPFSML(fi, LOGL_DEBUG, "%s: still active: %s\n",
157 __func__, sr->label);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200158 }
159 }
Harald Welteb8b85a12016-06-17 00:06:42 +0200160 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200161 }
Harald Welteb8b85a12016-06-17 00:06:42 +0200162
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200163 if ((trans = trans_has_conn(conn))) {
164 LOGPFSML(fi, LOGL_DEBUG,
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100165 "%s: connection still has active transaction: %s\n",
166 __func__, gsm48_pdisc_name(trans->protocol));
Harald Welteb8b85a12016-06-17 00:06:42 +0200167 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200168 }
Harald Welteb8b85a12016-06-17 00:06:42 +0200169
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100170 LOGPFSML(fi, LOGL_DEBUG, "%s: releasing conn\n", __func__);
Harald Welteb8b85a12016-06-17 00:06:42 +0200171 osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
172}
173
Harald Welte2483f1b2016-06-19 18:06:02 +0200174static void subscr_conn_fsm_accepted_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
175{
176 struct gsm_subscriber_connection *conn = fi->priv;
177 osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_ATTACHED, conn->vsub);
178}
179
Harald Welteb8b85a12016-06-17 00:06:42 +0200180static void subscr_conn_fsm_accepted(struct osmo_fsm_inst *fi, uint32_t event, void *data)
181{
182 switch (event) {
Harald Welte2483f1b2016-06-19 18:06:02 +0200183 case SUBSCR_CONN_E_COMMUNICATING:
184 osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_COMMUNICATING, 0, 0);
185 return;
186
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100187 case SUBSCR_CONN_E_RELEASE_WHEN_UNUSED:
188 subscr_conn_fsm_release_when_unused(fi, event, data);
Harald Welteb8b85a12016-06-17 00:06:42 +0200189 return;
190
191 default:
192 break;
193 }
194 /* Whatever unexpected happens in the accepted state, it means release.
195 * Even if an unexpected event is passed, the safest thing to do is
196 * discard the conn. We don't expect another SUBSCR_CONN_E_ACCEPTED. */
197 osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
198}
199
Harald Welte2483f1b2016-06-19 18:06:02 +0200200static void subscr_conn_fsm_communicating(struct osmo_fsm_inst *fi, uint32_t event, void *data)
201{
202 switch (event) {
203 case SUBSCR_CONN_E_COMMUNICATING:
204 /* no-op */
205 return;
206
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100207 case SUBSCR_CONN_E_RELEASE_WHEN_UNUSED:
208 subscr_conn_fsm_release_when_unused(fi, event, data);
Harald Welte2483f1b2016-06-19 18:06:02 +0200209 return;
210
211 default:
212 break;
213 }
214 /* Whatever unexpected happens in the accepted state, it means release.
215 * Even if an unexpected event is passed, the safest thing to do is
216 * discard the conn. We don't expect another SUBSCR_CONN_E_ACCEPTED. */
217 osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
218}
219
220static void subscr_conn_fsm_cleanup(struct osmo_fsm_inst *fi,
221 enum osmo_fsm_term_cause cause)
Harald Welteb8b85a12016-06-17 00:06:42 +0200222{
223 struct gsm_subscriber_connection *conn = fi->priv;
Harald Welte2483f1b2016-06-19 18:06:02 +0200224 fi->priv = NULL;
225
Harald Welteb8b85a12016-06-17 00:06:42 +0200226 if (!conn)
227 return;
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200228 conn->fi = NULL;
Harald Welte2483f1b2016-06-19 18:06:02 +0200229 msc_subscr_conn_close(conn, cause);
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100230 msc_subscr_conn_put(conn, MSC_CONN_USE_FSM);
Harald Welte2483f1b2016-06-19 18:06:02 +0200231}
Harald Welteb8b85a12016-06-17 00:06:42 +0200232
Harald Welte2483f1b2016-06-19 18:06:02 +0200233int subscr_conn_fsm_timeout(struct osmo_fsm_inst *fi)
234{
235 struct gsm_subscriber_connection *conn = fi->priv;
236 if (conn)
237 vlr_subscr_conn_timeout(conn->vsub);
Neels Hofmeyr3ddd7422017-11-18 23:25:41 +0100238 else
239 osmo_fsm_inst_dispatch(fi, SUBSCR_CONN_E_CN_CLOSE, NULL);
Harald Welte2483f1b2016-06-19 18:06:02 +0200240 return 0;
241}
242
243static void subscr_conn_fsm_release(struct osmo_fsm_inst *fi, uint32_t prev_state)
244{
245 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
Harald Welteb8b85a12016-06-17 00:06:42 +0200246}
247
248#define S(x) (1 << (x))
249
250static const struct osmo_fsm_state subscr_conn_fsm_states[] = {
Harald Welte2483f1b2016-06-19 18:06:02 +0200251 [SUBSCR_CONN_S_INIT] = {
252 .name = OSMO_STRINGIFY(SUBSCR_CONN_S_INIT),
253 .in_event_mask = S(SUBSCR_CONN_E_START),
254 .out_state_mask = S(SUBSCR_CONN_S_NEW),
255 .action = subscr_conn_fsm_init,
256 },
Harald Welteb8b85a12016-06-17 00:06:42 +0200257 [SUBSCR_CONN_S_NEW] = {
258 .name = OSMO_STRINGIFY(SUBSCR_CONN_S_NEW),
259 .in_event_mask = S(SUBSCR_CONN_E_ACCEPTED) |
260 S(SUBSCR_CONN_E_MO_CLOSE) |
Harald Welte2483f1b2016-06-19 18:06:02 +0200261 S(SUBSCR_CONN_E_CN_CLOSE),
Harald Welteb8b85a12016-06-17 00:06:42 +0200262 .out_state_mask = S(SUBSCR_CONN_S_ACCEPTED) |
263 S(SUBSCR_CONN_S_RELEASED),
264 .action = subscr_conn_fsm_new,
265 },
266 [SUBSCR_CONN_S_ACCEPTED] = {
267 .name = OSMO_STRINGIFY(SUBSCR_CONN_S_ACCEPTED),
268 /* allow everything to release for any odd behavior */
Harald Welte2483f1b2016-06-19 18:06:02 +0200269 .in_event_mask = S(SUBSCR_CONN_E_COMMUNICATING) |
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100270 S(SUBSCR_CONN_E_RELEASE_WHEN_UNUSED) |
Harald Welte2483f1b2016-06-19 18:06:02 +0200271 S(SUBSCR_CONN_E_ACCEPTED) |
Harald Welteb8b85a12016-06-17 00:06:42 +0200272 S(SUBSCR_CONN_E_MO_CLOSE) |
Harald Welte2483f1b2016-06-19 18:06:02 +0200273 S(SUBSCR_CONN_E_CN_CLOSE),
274 .out_state_mask = S(SUBSCR_CONN_S_RELEASED) |
275 S(SUBSCR_CONN_S_COMMUNICATING),
276 .onenter = subscr_conn_fsm_accepted_enter,
Harald Welteb8b85a12016-06-17 00:06:42 +0200277 .action = subscr_conn_fsm_accepted,
278 },
Harald Welte2483f1b2016-06-19 18:06:02 +0200279 [SUBSCR_CONN_S_COMMUNICATING] = {
280 .name = OSMO_STRINGIFY(SUBSCR_CONN_S_COMMUNICATING),
281 /* allow everything to release for any odd behavior */
Neels Hofmeyre9e2f5c2018-03-15 13:26:43 +0100282 .in_event_mask = S(SUBSCR_CONN_E_RELEASE_WHEN_UNUSED) |
Harald Welte2483f1b2016-06-19 18:06:02 +0200283 S(SUBSCR_CONN_E_ACCEPTED) |
284 S(SUBSCR_CONN_E_COMMUNICATING) |
285 S(SUBSCR_CONN_E_MO_CLOSE) |
286 S(SUBSCR_CONN_E_CN_CLOSE),
287 .out_state_mask = S(SUBSCR_CONN_S_RELEASED),
288 .action = subscr_conn_fsm_communicating,
289 },
Harald Welteb8b85a12016-06-17 00:06:42 +0200290 [SUBSCR_CONN_S_RELEASED] = {
291 .name = OSMO_STRINGIFY(SUBSCR_CONN_S_RELEASED),
292 .onenter = subscr_conn_fsm_release,
293 },
294};
295
296static struct osmo_fsm subscr_conn_fsm = {
297 .name = "Subscr_Conn",
298 .states = subscr_conn_fsm_states,
299 .num_states = ARRAY_SIZE(subscr_conn_fsm_states),
300 .allstate_event_mask = 0,
301 .allstate_action = NULL,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200302 .log_subsys = DMM,
Harald Welteb8b85a12016-06-17 00:06:42 +0200303 .event_names = subscr_conn_fsm_event_names,
Harald Welte2483f1b2016-06-19 18:06:02 +0200304 .cleanup = subscr_conn_fsm_cleanup,
305 .timer_cb = subscr_conn_fsm_timeout,
Harald Welteb8b85a12016-06-17 00:06:42 +0200306};
307
Daniel Willmann4e825b62018-02-15 10:33:26 +0100308char *msc_subscr_conn_get_conn_id(struct gsm_subscriber_connection *conn)
309{
310 char *id;
311
312 switch (conn->via_ran) {
313 case RAN_GERAN_A:
314 id = talloc_asprintf(conn, "GERAN_A-%08x", conn->a.conn_id);
315 break;
316 case RAN_UTRAN_IU:
317 id = talloc_asprintf(conn, "UTRAN_IU-%08x", iu_get_conn_id(conn->iu.ue_ctx));
318 break;
319 default:
320 LOGP(DMM, LOGL_ERROR, "RAN of conn %p unknown!\n", conn);
321 return NULL;
322 }
323
324 return id;
325}
326
Harald Welteb8b85a12016-06-17 00:06:42 +0200327int msc_create_conn_fsm(struct gsm_subscriber_connection *conn, const char *id)
328{
329 struct osmo_fsm_inst *fi;
330 OSMO_ASSERT(conn);
331
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200332 if (conn->fi) {
Harald Welteb8b85a12016-06-17 00:06:42 +0200333 LOGP(DMM, LOGL_ERROR,
334 "%s: Error: connection already in use\n", id);
335 return -EINVAL;
336 }
337
Harald Welte2483f1b2016-06-19 18:06:02 +0200338 /* Allocate the FSM not with the subscr_conn. Semantically it would
339 * make sense, but in subscr_conn_fsm_cleanup(), we want to discard the
340 * subscriber connection. If the FSM is freed along with the subscriber
341 * connection, then in _osmo_fsm_inst_term() the osmo_fsm_inst_free()
342 * that follows the cleanup() call would run into a double free. */
343 fi = osmo_fsm_inst_alloc(&subscr_conn_fsm, conn->network,
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100344 msc_subscr_conn_get(conn, MSC_CONN_USE_FSM),
Harald Welte2483f1b2016-06-19 18:06:02 +0200345 LOGL_DEBUG, id);
Harald Welteb8b85a12016-06-17 00:06:42 +0200346
347 if (!fi) {
348 LOGP(DMM, LOGL_ERROR,
349 "%s: Failed to allocate subscr conn master FSM\n", id);
350 return -ENOMEM;
351 }
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200352 conn->fi = fi;
353 osmo_fsm_inst_dispatch(conn->fi, SUBSCR_CONN_E_START, NULL);
Harald Welteb8b85a12016-06-17 00:06:42 +0200354 return 0;
355}
356
Maxd83b17b2018-02-06 16:51:31 +0100357bool msc_subscr_conn_is_accepted(const struct gsm_subscriber_connection *conn)
Harald Welteb8b85a12016-06-17 00:06:42 +0200358{
359 if (!conn)
360 return false;
Harald Welte2483f1b2016-06-19 18:06:02 +0200361 if (!conn->vsub)
Harald Welteb8b85a12016-06-17 00:06:42 +0200362 return false;
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200363 if (!conn->fi)
Harald Welteb8b85a12016-06-17 00:06:42 +0200364 return false;
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200365 if (!(conn->fi->state == SUBSCR_CONN_S_ACCEPTED
366 || conn->fi->state == SUBSCR_CONN_S_COMMUNICATING))
Harald Welteb8b85a12016-06-17 00:06:42 +0200367 return false;
368 return true;
369}
370
Harald Welte2483f1b2016-06-19 18:06:02 +0200371void msc_subscr_conn_communicating(struct gsm_subscriber_connection *conn)
372{
373 OSMO_ASSERT(conn);
Neels Hofmeyrd6a769b2018-03-12 23:59:07 +0100374 /* This function is called to indicate that *some* communication is happening with the phone.
375 * Late in the process, that may be a Release Confirm and the FSM and conn are already in
376 * teardown. No need to signal SUBSCR_CONN_E_COMMUNICATING then. */
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200377 if (conn->fi)
378 osmo_fsm_inst_dispatch(conn->fi, SUBSCR_CONN_E_COMMUNICATING, NULL);
Harald Welte2483f1b2016-06-19 18:06:02 +0200379}
380
Harald Welteb8b85a12016-06-17 00:06:42 +0200381void msc_subscr_conn_init(void)
382{
383 osmo_fsm_register(&subscr_conn_fsm);
384}