FreeCalypso > hg > themwi-system-sw
view mncc/extsock.c @ 97:9aed16c30622
mgw p2g: set M bit when restarting forwarding after no-forward
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 25 Sep 2022 20:05:02 -0800 |
parents | 660126bd5f59 |
children |
line wrap: on
line source
/* * 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); }