[mobile] Using socket application interface with mobile application

Use "-m" with mobile app, to use it in conjunction with LCR or other
applications.
This commit is contained in:
Andreas Eversberg 2011-09-02 11:16:10 +02:00
parent 5c8b76e74e
commit c9927c72ea
9 changed files with 116 additions and 37 deletions

View File

@ -18,6 +18,7 @@ struct osmocom_ms;
#include <osmocom/bb/mobile/gsm322.h>
#include <osmocom/bb/mobile/gsm48_mm.h>
#include <osmocom/bb/mobile/gsm48_cc.h>
#include <osmocom/bb/mobile/mncc_sock.h>
#include <osmocom/bb/common/sim.h>
#include <osmocom/bb/common/l1ctl.h>
@ -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;
};

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;