FreeCalypso > hg > themwi-interim
diff mncc/extsock.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/extsock.c Sat Jun 08 23:12:12 2024 +0000 @@ -0,0 +1,243 @@ +/* + * In this module we gather functions that deal with external + * socket connections, both externally-originating MT calls + * and outbound MO calls. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <syslog.h> +#include "../include/mncc.h" +#include "../include/gsm48_const.h" +#include "struct.h" +#include "gsm_call.h" + +extern char *mncc_msg_name(); + +void +extsock_dec_refcount(conn) + struct socket_conn *conn; +{ + if (!conn->ncalls) { + syslog(LOG_CRIT, "FATAL BUG: ncalls=0 on socket call clearing"); + exit(1); + } + conn->ncalls--; +} + +static void +send_rel_on_broken_socket(call) + struct gsm_call *call; +{ + struct gsm_mncc msg; + + bzero(&msg, sizeof(struct gsm_mncc)); + msg.msg_type = MNCC_REL_REQ; + msg.callref = call->callref; + mncc_set_cause(&msg, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_DEST_OOO); + send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc)); +} + +static void +broken_socket_clear_calls(conn) + struct socket_conn *conn; +{ + extern struct gsm_call *call_list_head; + struct gsm_call *call; + + for (call = call_list_head; call; call = call->next) { + if (call->gc_flag) + continue; + if (call->socket == conn) { + syslog(LOG_WARNING, + "clearing broken socket call: GSM callref 0x%x, socket ref 0x%x", + call->callref, call->socket_ref); + send_rel_on_broken_socket(call); + extsock_dec_refcount(conn); + call->gc_flag = 1; + } + } + if (conn->ncalls) { + syslog(LOG_CRIT, + "FATAL BUG: ncalls!=0 after broken socket call clearing"); + exit(1); + } +} + +static void +report_runt(msg) + union mncc_msg *msg; +{ + syslog(LOG_CRIT, + "MNCC message type 0x%x from ThemWi call socket is too short!", + msg->msg_type); +} + +static void +handle_setup_req(conn, msg, msglen) + struct socket_conn *conn; + 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_REQ from socket, callref=0x%x", + msg->callref); + call = find_socket_call(conn, msg->callref); + if (call) { + syslog(LOG_ERR, + "duplicate MNCC_SETUP_REQ from socket for callref 0x%x", + msg->callref); + /* drop it like OsmoMSC's mncc_builtin does */ + return; + } + /* further processing */ + process_ext_mtcall_setup(conn, msg); +} + +static void +handle_signaling_msg(conn, msg, msglen) + struct socket_conn *conn; + 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 socket, callref=0x%x", + mncc_msg_name(msg->msg_type), msg->callref); + call = find_socket_call(conn, msg->callref); + if (!call) { + syslog(LOG_ERR, + "MNCC message from ThemWi call socket: callref 0x%x not found", + msg->callref); + /* drop it like OsmoMSC's mncc_builtin does */ + return; + } + /* forward to GSM MNCC interface */ + msg->callref = call->callref; + send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); + if (msg->msg_type == MNCC_REJ_REQ) { + extsock_dec_refcount(conn); + call->gc_flag = 1; + } +} + +static void +handle_rtp_msg(conn, msg, msglen) + struct socket_conn *conn; + 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 socket, callref=0x%x", + mncc_msg_name(msg->msg_type), msg->callref); + call = find_socket_call(conn, msg->callref); + if (!call) { + syslog(LOG_ERR, + "MNCC message from ThemWi call socket: callref 0x%x not found", + msg->callref); + /* drop it like OsmoMSC's mncc_builtin does */ + return; + } + /* forward to GSM MNCC interface */ + msg->callref = call->callref; + send_mncc_to_gsm(msg, sizeof(struct gsm_mncc_rtp)); +} + +void +extsock_read_select(conn) + struct socket_conn *conn; +{ + union mncc_msg msg; + int rc; + + rc = recv(conn->fd, &msg, sizeof msg, 0); + if (rc < 4) { + if (conn->ncalls) { + syslog(LOG_ERR, "ext socket broken with calls present"); + broken_socket_clear_calls(conn); + } else + syslog(LOG_INFO, "normal closing of ext socket"); + close(conn->fd); + conn->fd = -1; + return; + } + switch (msg.msg_type) { + case MNCC_SETUP_REQ: + handle_setup_req(conn, &msg, rc); + return; + case MNCC_SETUP_RSP: + case MNCC_SETUP_COMPL_REQ: + case MNCC_CALL_PROC_REQ: + case MNCC_PROGRESS_REQ: + case MNCC_ALERT_REQ: + case MNCC_NOTIFY_REQ: + case MNCC_DISC_REQ: + case MNCC_REL_REQ: + case MNCC_FACILITY_REQ: + case MNCC_START_DTMF_RSP: + case MNCC_START_DTMF_REJ: + case MNCC_STOP_DTMF_RSP: + case MNCC_MODIFY_REQ: + case MNCC_MODIFY_RSP: + case MNCC_MODIFY_REJ: + case MNCC_HOLD_CNF: + case MNCC_HOLD_REJ: + case MNCC_RETRIEVE_CNF: + case MNCC_RETRIEVE_REJ: + case MNCC_USERINFO_REQ: + case MNCC_REJ_REQ: + handle_signaling_msg(conn, &msg, rc); + return; + case MNCC_RTP_CREATE: + case MNCC_RTP_CONNECT: + case MNCC_RTP_FREE: + handle_rtp_msg(conn, &msg, rc); + return; + default: + syslog(LOG_CRIT, + "unknown MNCC message type 0x%x from ThemWi call socket", + msg.msg_type); + } +} + +mncc_signal_to_socket(call, msg) + struct gsm_call *call; + struct gsm_mncc *msg; +{ + msg->callref = call->socket_ref; + return send(call->socket->fd, msg, sizeof(struct gsm_mncc), 0); +} + +mncc_signal_to_socket_nocall(conn, msg) + struct socket_conn *conn; + struct gsm_mncc *msg; +{ + return send(conn->fd, msg, sizeof(struct gsm_mncc), 0); +} + +mncc_rtp_to_socket(call, msg) + struct gsm_call *call; + struct gsm_mncc_rtp *msg; +{ + msg->callref = call->socket_ref; + return send(call->socket->fd, msg, sizeof(struct gsm_mncc_rtp), 0); +}