FreeCalypso > hg > themwi-interim
diff mncc/mncc_recv.c @ 2:053f04687106
mncc: initial import from old ThemWi
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 08 Jun 2024 23:12:12 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mncc/mncc_recv.c Sat Jun 08 23:12:12 2024 +0000 @@ -0,0 +1,198 @@ +/* + * In this module we implement initial handling of MNCC messages + * coming from OsmoMSC, dispatching them further as appropriate. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <syslog.h> +#include "../include/mncc.h" +#include "struct.h" +#include "gsm_call.h" + +extern char *mncc_msg_name(); + +static void +report_runt(msg) + union mncc_msg *msg; +{ + syslog(LOG_CRIT, "MNCC message type 0x%x from GSM is too short!", + msg->msg_type); +} + +static void +handle_setup_ind(msg, msglen) + struct gsm_mncc *msg; + unsigned msglen; +{ + struct gsm_call *call; + + if (msglen < sizeof(struct gsm_mncc)) { + report_runt(msg); + return; + } + syslog(LOG_DEBUG, "Rx MNCC_SETUP_IND from GSM, callref=0x%x", + msg->callref); + call = find_gsm_callref(msg->callref); + if (call) { + syslog(LOG_ERR, "duplicate MNCC_SETUP_IND for callref 0x%x", + msg->callref); + /* drop it like OsmoMSC's mncc_builtin does */ + return; + } + /* further processing */ + process_mo_call_setup(msg); +} + +static void +handle_signaling_msg(msg, msglen) + struct gsm_mncc *msg; + unsigned msglen; +{ + struct gsm_call *call; + + if (msglen < sizeof(struct gsm_mncc)) { + report_runt(msg); + return; + } + syslog(LOG_DEBUG, "Rx %s from GSM, callref=0x%x", + mncc_msg_name(msg->msg_type), msg->callref); + call = find_gsm_callref(msg->callref); + if (!call) { + syslog(LOG_ERR, "%s from GSM: callref 0x%x not found", + mncc_msg_name(msg->msg_type), msg->callref); + /* drop it like OsmoMSC's mncc_builtin does */ + return; + } + if (msg->msg_type == MNCC_SETUP_CNF) + preen_connected_number(msg); + /* dispatch according to internal switch or socket */ + if (call->socket) + mncc_signal_to_socket(call, msg); + else + internal_switch_mncc(call, msg); +} + +static void +handle_release_msg(msg, msglen) + struct gsm_mncc *msg; + unsigned msglen; +{ + struct gsm_call *call; + + if (msglen < sizeof(struct gsm_mncc)) { + report_runt(msg); + return; + } + syslog(LOG_DEBUG, "Rx %s from GSM, callref=0x%x", + mncc_msg_name(msg->msg_type), msg->callref); + call = find_gsm_callref(msg->callref); + if (!call) { + syslog(LOG_ERR, "%s from GSM: callref 0x%x not found", + mncc_msg_name(msg->msg_type), msg->callref); + /* drop it like OsmoMSC's mncc_builtin does */ + return; + } + /* dispatch according to internal switch or socket */ + if (call->socket) { + mncc_signal_to_socket(call, msg); + syslog(LOG_DEBUG, + "clearing socket call: GSM callref 0x%x, socket ref 0x%x", + call->callref, call->socket_ref); + extsock_dec_refcount(call->socket); + call->gc_flag = 1; + } else + internal_switch_mncc(call, msg); +} + +static void +handle_rtp_msg(msg, msglen) + struct gsm_mncc_rtp *msg; + unsigned msglen; +{ + struct gsm_call *call; + + if (msglen < sizeof(struct gsm_mncc_rtp)) { + report_runt(msg); + return; + } + syslog(LOG_DEBUG, "Rx %s from GSM, callref=0x%x", + mncc_msg_name(msg->msg_type), msg->callref); + call = find_gsm_callref(msg->callref); + if (!call) { + syslog(LOG_ERR, "%s from GSM: callref 0x%x not found", + mncc_msg_name(msg->msg_type), msg->callref); + /* drop it like OsmoMSC's mncc_builtin does */ + return; + } + /* only for socket connections - no RTP handling for internal */ + if (call->socket) + mncc_rtp_to_socket(call, msg); +} + +static void +handle_mncc_hello(msg, msglen) + struct gsm_mncc_hello *msg; + unsigned msglen; +{ + if (msglen < sizeof(struct gsm_mncc_hello)) { + syslog(LOG_CRIT, "MNCC_SOCKET_HELLO message is too short!"); + exit(1); + } + if (msg->version != MNCC_SOCK_VERSION) { + syslog(LOG_CRIT, "MNCC hello error: version number mismatch"); + exit(1); + } + if (msg->mncc_size != sizeof(struct gsm_mncc)) { + syslog(LOG_CRIT, "MNCC hello error: mncc_size mismatch"); + exit(1); + } +} + +void +mncc_msg_from_gsm(msg, msglen) + union mncc_msg *msg; + unsigned msglen; +{ + switch (msg->msg_type) { + case MNCC_SETUP_IND: + handle_setup_ind(msg, msglen); + return; + case MNCC_SETUP_CNF: + case MNCC_SETUP_COMPL_IND: + case MNCC_CALL_CONF_IND: + case MNCC_ALERT_IND: + case MNCC_NOTIFY_IND: + case MNCC_DISC_IND: + case MNCC_FACILITY_IND: + case MNCC_START_DTMF_IND: + case MNCC_STOP_DTMF_IND: + case MNCC_MODIFY_IND: + case MNCC_MODIFY_CNF: + case MNCC_MODIFY_REJ: + case MNCC_HOLD_IND: + case MNCC_RETRIEVE_IND: + case MNCC_USERINFO_IND: + handle_signaling_msg(msg, msglen); + return; + case MNCC_REL_IND: + case MNCC_REL_CNF: + case MNCC_REJ_IND: + handle_release_msg(msg, msglen); + return; + case MNCC_RTP_CREATE: + case MNCC_RTP_CONNECT: + case MNCC_RTP_FREE: + handle_rtp_msg(msg, msglen); + return; + case MNCC_SOCKET_HELLO: + handle_mncc_hello(msg, msglen); + return; + default: + syslog(LOG_CRIT, "unknown MNCC message type 0x%x from GSM", + msg->msg_type); + } +}