From c9927c72ea31ad00b23da122280d6fcdec4a1a1e Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Fri, 2 Sep 2011 11:16:10 +0200 Subject: [PATCH] [mobile] Using socket application interface with mobile application Use "-m" with mobile app, to use it in conjunction with LCR or other applications. --- .../include/osmocom/bb/common/osmocom_data.h | 2 + .../include/osmocom/bb/mobile/Makefile.am | 2 +- .../include/osmocom/bb/mobile/gsm48_cc.h | 3 +- .../layer23/include/osmocom/bb/mobile/mncc.h | 3 - src/host/layer23/src/mobile/Makefile.am | 2 +- src/host/layer23/src/mobile/app_mobile.c | 22 ++----- src/host/layer23/src/mobile/gsm48_cc.c | 45 +++++++++++++- src/host/layer23/src/mobile/main.c | 16 ++++- src/host/layer23/src/mobile/mnccms.c | 58 +++++++++++++++---- 9 files changed, 116 insertions(+), 37 deletions(-) diff --git a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h index 6ad89cd37..8f150078f 100644 --- a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h +++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h @@ -18,6 +18,7 @@ struct osmocom_ms; #include #include #include +#include #include #include @@ -31,6 +32,7 @@ struct osmol1_entity { struct osmomncc_entity { int (*mncc_recv)(struct osmocom_ms *ms, int msg_type, void *arg); + struct mncc_sock_state *sock_state; uint32_t ref; }; diff --git a/src/host/layer23/include/osmocom/bb/mobile/Makefile.am b/src/host/layer23/include/osmocom/bb/mobile/Makefile.am index 951e4d19e..65b7ce763 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/Makefile.am +++ b/src/host/layer23/include/osmocom/bb/mobile/Makefile.am @@ -1,2 +1,2 @@ noinst_HEADERS = gsm322.h gsm48_cc.h gsm48_mm.h gsm48_rr.h mncc.h settings.h \ - subscriber.h support.h transaction.h vty.h + subscriber.h support.h transaction.h vty.h mncc_sock.h diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h index 8cdd1c4f4..282ffe5b9 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h +++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h @@ -11,7 +11,8 @@ int gsm48_cc_init(struct osmocom_ms *ms); int gsm48_cc_exit(struct osmocom_ms *ms); int gsm48_rcv_cc(struct osmocom_ms *ms, struct msgb *msg); int mncc_dequeue(struct osmocom_ms *ms); -int mncc_send(struct osmocom_ms *ms, int msg_type, void *arg); +int mncc_tx_to_cc(void *inst, int msg_type, void *arg); +int mncc_clear_trans(void *inst, uint8_t protocol); #endif /* _GSM48_CC_H */ diff --git a/src/host/layer23/include/osmocom/bb/mobile/mncc.h b/src/host/layer23/include/osmocom/bb/mobile/mncc.h index a2b48cf7d..1d7f77942 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/mncc.h +++ b/src/host/layer23/include/osmocom/bb/mobile/mncc.h @@ -109,9 +109,6 @@ struct gsm_call { #define GSM_TCHF_FRAME 0x0300 #define GSM_TCHF_FRAME_EFR 0x0301 -#define MS_NEW 0x0400 -#define MS_DELETE 0x0401 - #define GSM_MAX_FACILITY 128 #define GSM_MAX_SSVERSION 128 #define GSM_MAX_USERUSER 128 diff --git a/src/host/layer23/src/mobile/Makefile.am b/src/host/layer23/src/mobile/Makefile.am index e5cf76a78..4cff9efd4 100644 --- a/src/host/layer23/src/mobile/Makefile.am +++ b/src/host/layer23/src/mobile/Makefile.am @@ -5,7 +5,7 @@ LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOG noinst_LIBRARIES = libmobile.a libmobile_a_SOURCES = gsm322.c gsm48_cc.c gsm48_mm.c gsm48_rr.c \ mnccms.c settings.c subscriber.c support.c \ - transaction.c vty_interface.c voice.c + transaction.c vty_interface.c voice.c mncc_sock.c bin_PROGRAMS = mobile diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c index 8b3b55240..ada948099 100644 --- a/src/host/layer23/src/mobile/app_mobile.c +++ b/src/host/layer23/src/mobile/app_mobile.c @@ -233,16 +233,13 @@ struct osmocom_ms *mobile_new(char *name) ms->shutdown = 2; /* being down */ if (mncc_recv_app) { - struct msgb *msg; + char name[32]; - msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC"); - if (msg) { - struct gsm_mncc *mncc = (struct gsm_mncc *)msg->data; + sprintf(name, "/tmp/ms_mncc_%s", ms->name); - mncc->msg_type = MS_NEW; - mncc_recv_app(ms, mncc->msg_type, mncc); - } ms->mncc_entity.mncc_recv = mncc_recv_app; + ms->mncc_entity.sock_state = mncc_sock_init(ms, name, l23_ctx); + } else if (ms->settings.ch_cap == GSM_CAP_SDCCH) ms->mncc_entity.mncc_recv = mncc_recv_dummy; else @@ -266,15 +263,8 @@ int mobile_delete(struct osmocom_ms *ms, int force) } if (mncc_recv_app) { - struct msgb *msg; - - msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC"); - if (msg) { - struct gsm_mncc *mncc = (struct gsm_mncc *)msg->data; - - mncc->msg_type = MS_DELETE; - mncc_recv_app(ms, mncc->msg_type, mncc); - } + mncc_sock_exit(ms->mncc_entity.sock_state); + ms->mncc_entity.sock_state = NULL; } return 0; diff --git a/src/host/layer23/src/mobile/gsm48_cc.c b/src/host/layer23/src/mobile/gsm48_cc.c index 07ee2d9b6..2e978197b 100644 --- a/src/host/layer23/src/mobile/gsm48_cc.c +++ b/src/host/layer23/src/mobile/gsm48_cc.c @@ -76,9 +76,10 @@ int gsm48_cc_exit(struct osmocom_ms *ms) LOGP(DCC, LOGL_INFO, "exit Call Control processes for %s\n", ms->name); llist_for_each_entry_safe(trans, trans2, &ms->trans_list, entry) { - if (trans->protocol == GSM48_PDISC_CC) + if (trans->protocol == GSM48_PDISC_CC) { LOGP(DCC, LOGL_NOTICE, "Free pendig CC-transaction.\n"); trans_free(trans); + } } while ((msg = msgb_dequeue(&cc->mncc_upqueue))) @@ -1916,12 +1917,29 @@ static struct downstate { #define DOWNSLLEN \ (sizeof(downstatelist) / sizeof(struct downstate)) -int mncc_send(struct osmocom_ms *ms, int msg_type, void *arg) +int mncc_tx_to_cc(void *inst, int msg_type, void *arg) { + struct osmocom_ms *ms = (struct osmocom_ms *) inst; struct gsm_mncc *data = arg; struct gsm_trans *trans; int i, rc; + if (!ms->started || ms->shutdown) { + LOGP(DCC, LOGL_NOTICE, "Phone is down!\n"); + if (ms->mncc_entity.mncc_recv && msg_type != MNCC_REL_REQ) { + struct gsm_mncc rel; + + memset(&rel, 0, sizeof(rel)); + rel.callref = data->callref; + mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_DEST_OOO); + ms->mncc_entity.mncc_recv(ms, MNCC_REL_IND, &rel); + } + return -EBUSY; + } + + data->msg_type = msg_type; + /* Find callref */ trans = trans_find_by_callref(ms, data->callref); @@ -2179,3 +2197,26 @@ int gsm48_rcv_cc(struct osmocom_ms *ms, struct msgb *msg) return rc; } +int mncc_clear_trans(void *inst, uint8_t protocol) +{ + struct osmocom_ms *ms = (struct osmocom_ms *) inst; + struct gsm_mncc rel; + struct gsm_trans *trans, *trans2; + + memset(&rel, 0, sizeof(struct gsm_mncc)); + + /* safe, in case the release process will destroy transaction node */ + llist_for_each_entry_safe(trans, trans2, &ms->trans_list, entry) { + if (trans->protocol == protocol) { + LOGP(DCC, LOGL_NOTICE, "Release CC-transaction.\n"); + rel.callref = trans->callref; + mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_TEMP_FAILURE); + mncc_tx_to_cc(ms, MNCC_REL_REQ, &rel); + } + } + + return 0; + +} + diff --git a/src/host/layer23/src/mobile/main.c b/src/host/layer23/src/mobile/main.c index ed961c575..5739bfde2 100644 --- a/src/host/layer23/src/mobile/main.c +++ b/src/host/layer23/src/mobile/main.c @@ -54,6 +54,9 @@ struct gsmtap_inst *gsmtap_inst = NULL; unsigned short vty_port = 4247; int debug_set = 0; char *config_dir = NULL; +int use_mncc_sock = 0; + +int mncc_recv_socket(struct osmocom_ms *ms, int msg_type, void *arg); int mobile_delete(struct osmocom_ms *ms, int force); int mobile_signal_cb(unsigned int subsys, unsigned int signal, @@ -83,6 +86,8 @@ static void print_help() printf(" -v --vty-port The VTY port number to telnet to. " "(default %u)\n", vty_port); printf(" -d --debug Change debug flags.\n"); + printf(" -m --mncc-sock Disable built-in MNCC handler and " + "offer socket\n"); } static void handle_options(int argc, char **argv) @@ -94,10 +99,11 @@ static void handle_options(int argc, char **argv) {"gsmtap-ip", 1, 0, 'i'}, {"vty-port", 1, 0, 'v'}, {"debug", 1, 0, 'd'}, + {"mncc-sock", 0, 0, 'm'}, {0, 0, 0, 0}, }; - c = getopt_long(argc, argv, "hi:v:d:", + c = getopt_long(argc, argv, "hi:v:d:m", long_options, &option_index); if (c == -1) break; @@ -118,6 +124,9 @@ static void handle_options(int argc, char **argv) log_parse_category_mask(stderr_target, optarg); debug_set = 1; break; + case 'm': + use_mncc_sock = 1; + break; default: break; } @@ -187,7 +196,10 @@ int main(int argc, char **argv) config_dir = talloc_strdup(l23_ctx, config_file); config_dir = dirname(config_dir); - rc = l23_app_init(NULL, config_file, vty_port); + if (use_mncc_sock) + rc = l23_app_init(mncc_recv_socket, config_file, vty_port); + else + rc = l23_app_init(NULL, config_file, vty_port); if (rc) exit(rc); diff --git a/src/host/layer23/src/mobile/mnccms.c b/src/host/layer23/src/mobile/mnccms.c index 8d3abe68a..c6db1abba 100644 --- a/src/host/layer23/src/mobile/mnccms.c +++ b/src/host/layer23/src/mobile/mnccms.c @@ -216,7 +216,43 @@ int mncc_recv_dummy(struct osmocom_ms *ms, int msg_type, void *arg) mncc_set_cause(&rel, GSM48_CAUSE_LOC_USER, GSM48_CC_CAUSE_INCOMPAT_DEST); - return mncc_send(ms, MNCC_REL_REQ, &rel); + return mncc_tx_to_cc(ms, MNCC_REL_REQ, &rel); +} + +/* + * MNCCms call application via socket + */ +int mncc_recv_socket(struct osmocom_ms *ms, int msg_type, void *arg) +{ + struct mncc_sock_state *state = ms->mncc_entity.sock_state; + struct gsm_mncc *mncc = arg; + struct msgb *msg; + unsigned char *data; + + if (!state) { + if (msg_type != MNCC_REL_IND && msg_type != MNCC_REL_CNF) { + struct gsm_mncc rel; + + /* reject */ + memset(&rel, 0, sizeof(struct gsm_mncc)); + rel.callref = mncc->callref; + mncc_set_cause(&rel, GSM48_CAUSE_LOC_USER, + GSM48_CC_CAUSE_TEMP_FAILURE); + return mncc_tx_to_cc(ms, MNCC_REL_REQ, &rel); + } + return 0; + } + + mncc->msg_type = msg_type; + + msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC"); + if (!msg) + return -ENOMEM; + + data = msgb_put(msg, sizeof(struct gsm_mncc)); + memcpy(data, mncc, sizeof(struct gsm_mncc)); + + return mncc_sock_from_cc(state, msg); } /* @@ -244,7 +280,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg) memset(&mncc, 0, sizeof(struct gsm_mncc)); mncc.callref = data->callref; mncc_set_cause(&mncc, GSM48_CAUSE_LOC_USER, cause); - return mncc_send(ms, MNCC_REL_REQ, &mncc); + return mncc_tx_to_cc(ms, MNCC_REL_REQ, &mncc); } /* setup without call */ @@ -439,7 +475,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg) mncc.fields |= MNCC_F_CCCAP; mncc.cccap.dtmf = 1; } - mncc_send(ms, MNCC_CALL_CONF_REQ, &mncc); + mncc_tx_to_cc(ms, MNCC_CALL_CONF_REQ, &mncc); if (first_call) LOGP(DMNCC, LOGL_INFO, "Ring!\n"); else { @@ -449,7 +485,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg) call->ring = 1; memset(&mncc, 0, sizeof(struct gsm_mncc)); mncc.callref = call->callref; - mncc_send(ms, MNCC_ALERT_REQ, &mncc); + mncc_tx_to_cc(ms, MNCC_ALERT_REQ, &mncc); if (ms->settings.auto_answer) { LOGP(DMNCC, LOGL_INFO, "Auto-answering call\n"); mncc_answer(ms); @@ -558,7 +594,7 @@ int mncc_call(struct osmocom_ms *ms, char *number) } } - return mncc_send(ms, MNCC_SETUP_REQ, &setup); + return mncc_tx_to_cc(ms, MNCC_SETUP_REQ, &setup); } int mncc_hangup(struct osmocom_ms *ms) @@ -583,7 +619,7 @@ int mncc_hangup(struct osmocom_ms *ms) disc.callref = found->callref; mncc_set_cause(&disc, GSM48_CAUSE_LOC_USER, GSM48_CC_CAUSE_NORM_CALL_CLEAR); - return mncc_send(ms, (call->init) ? MNCC_REL_REQ : MNCC_DISC_REQ, + return mncc_tx_to_cc(ms, (call->init) ? MNCC_REL_REQ : MNCC_DISC_REQ, &disc); } @@ -616,7 +652,7 @@ int mncc_answer(struct osmocom_ms *ms) memset(&rsp, 0, sizeof(struct gsm_mncc)); rsp.callref = alerting->callref; - return mncc_send(ms, MNCC_SETUP_RSP, &rsp); + return mncc_tx_to_cc(ms, MNCC_SETUP_RSP, &rsp); } int mncc_hold(struct osmocom_ms *ms) @@ -639,7 +675,7 @@ int mncc_hold(struct osmocom_ms *ms) memset(&hold, 0, sizeof(struct gsm_mncc)); hold.callref = found->callref; - return mncc_send(ms, MNCC_HOLD_REQ, &hold); + return mncc_tx_to_cc(ms, MNCC_HOLD_REQ, &hold); } int mncc_retrieve(struct osmocom_ms *ms, int number) @@ -687,7 +723,7 @@ int mncc_retrieve(struct osmocom_ms *ms, int number) memset(&retr, 0, sizeof(struct gsm_mncc)); retr.callref = call->callref; - return mncc_send(ms, MNCC_RETRIEVE_REQ, &retr); + return mncc_tx_to_cc(ms, MNCC_RETRIEVE_REQ, &retr); } /* @@ -714,7 +750,7 @@ static int dtmf_statemachine(struct gsm_call *call, struct gsm_mncc *mncc) call->dtmf_state = DTMF_ST_START; LOGP(DMNCC, LOGL_INFO, "start DTMF (keypad %c)\n", dtmf.keypad); - return mncc_send(ms, MNCC_START_DTMF_REQ, &dtmf); + return mncc_tx_to_cc(ms, MNCC_START_DTMF_REQ, &dtmf); case DTMF_ST_START: if (mncc->msg_type != MNCC_START_DTMF_RSP) { LOGP(DMNCC, LOGL_INFO, "DTMF was rejected\n"); @@ -729,7 +765,7 @@ static int dtmf_statemachine(struct gsm_call *call, struct gsm_mncc *mncc) dtmf.callref = call->callref; call->dtmf_state = DTMF_ST_STOP; LOGP(DMNCC, LOGL_INFO, "stop DTMF\n"); - return mncc_send(ms, MNCC_STOP_DTMF_REQ, &dtmf); + return mncc_tx_to_cc(ms, MNCC_STOP_DTMF_REQ, &dtmf); case DTMF_ST_STOP: start_dtmf_timer(call, 120); call->dtmf_state = DTMF_ST_SPACE;