diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2017-11-18 08:33:07 +0100 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2017-12-03 08:45:54 +0100 |
commit | ab59a26a519d4bfb88f9ca6f882da8baab90a95a (patch) | |
tree | 1c49655c2344a3bd5edc4e76948eaa33d7754e1c /src/common/call.c | |
parent | ed31a26ebabcd28678aff679093b6e6fba55b67f (diff) |
Restructure: Move mobile from common code to 'libmobile'
Diffstat (limited to 'src/common/call.c')
-rw-r--r-- | src/common/call.c | 790 |
1 files changed, 0 insertions, 790 deletions
diff --git a/src/common/call.c b/src/common/call.c deleted file mode 100644 index 85c0e9f..0000000 --- a/src/common/call.c +++ /dev/null @@ -1,790 +0,0 @@ -/* interface between mobile network/phone implementation and MNCC - * - * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu> - * All Rights Reserved - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdint.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/time.h> -#include "../libsample/sample.h" -#include "debug.h" -#include "sender.h" -#include "call.h" -#include "../libtimer/timer.h" -#include "../libmncc/mncc.h" -#include "../libmncc/cause.h" - -#define DISC_TIMEOUT 30 - -//#define DEBUG_LEVEL - -#ifdef DEBUG_LEVEL -static double level_of(double *samples, int count) -{ - double level = 0; - int i; - - for (i = 0; i < count; i++) { - if (samples[i] > level) - level = samples[i]; - } - - return level; -} -#endif - -static int send_patterns; /* send patterns towards fixed network */ -static int release_on_disconnect; /* release towards mobile phone, if MNCC call disconnects, don't send disconnect tone */ - -/* stream patterns/announcements */ -int16_t *ringback_spl = NULL; -int ringback_size = 0; -int ringback_max = 0; -int16_t *hangup_spl = NULL; -int hangup_size = 0; -int hangup_max = 0; -int16_t *busy_spl = NULL; -int busy_size = 0; -int busy_max = 0; -int16_t *noanswer_spl = NULL; -int noanswer_size = 0; -int noanswer_max = 0; -int16_t *outoforder_spl = NULL; -int outoforder_size = 0; -int outoforder_max = 0; -int16_t *invalidnumber_spl = NULL; -int invalidnumber_size = 0; -int invalidnumber_max = 0; -int16_t *congestion_spl = NULL; -int congestion_size = 0; -int congestion_max = 0; -int16_t *recall_spl = NULL; -int recall_size = 0; -int recall_max = 0; - -enum audio_pattern { - PATTERN_NONE = 0, - PATTERN_TEST, - PATTERN_RINGBACK, - PATTERN_HANGUP, - PATTERN_BUSY, - PATTERN_NOANSWER, - PATTERN_OUTOFORDER, - PATTERN_INVALIDNUMBER, - PATTERN_CONGESTION, - PATTERN_RECALL, -}; - -static void get_pattern(const int16_t **spl, int *size, int *max, enum audio_pattern pattern) -{ - *spl = NULL; - *size = 0; - *max = 0; - - switch (pattern) { - case PATTERN_RINGBACK: -no_recall: - *spl = ringback_spl; - *size = ringback_size; - *max = ringback_max; - break; - case PATTERN_HANGUP: - if (!hangup_spl) - goto no_hangup; - *spl = hangup_spl; - *size = hangup_size; - *max = hangup_max; - break; - case PATTERN_BUSY: -no_hangup: -no_noanswer: - *spl = busy_spl; - *size = busy_size; - *max = busy_max; - break; - case PATTERN_NOANSWER: - if (!noanswer_spl) - goto no_noanswer; - *spl = noanswer_spl; - *size = noanswer_size; - *max = noanswer_max; - break; - case PATTERN_OUTOFORDER: - if (!outoforder_spl) - goto no_outoforder; - *spl = outoforder_spl; - *size = outoforder_size; - *max = outoforder_max; - break; - case PATTERN_INVALIDNUMBER: - if (!invalidnumber_spl) - goto no_invalidnumber; - *spl = invalidnumber_spl; - *size = invalidnumber_size; - *max = invalidnumber_max; - break; - case PATTERN_CONGESTION: -no_outoforder: -no_invalidnumber: - *spl = congestion_spl; - *size = congestion_size; - *max = congestion_max; - break; - case PATTERN_RECALL: - if (!recall_spl) - goto no_recall; - *spl = recall_spl; - *size = recall_size; - *max = recall_max; - break; - default: - ; - } -} - -static enum audio_pattern cause2pattern(int cause) -{ - int pattern; - - switch (cause) { - case CAUSE_NORMAL: - pattern = PATTERN_HANGUP; - break; - case CAUSE_BUSY: - pattern = PATTERN_BUSY; - break; - case CAUSE_NOANSWER: - pattern = PATTERN_NOANSWER; - break; - case CAUSE_OUTOFORDER: - pattern = PATTERN_OUTOFORDER; - break; - case CAUSE_INVALNUMBER: - pattern = PATTERN_INVALIDNUMBER; - break; - case CAUSE_NOCHANNEL: - pattern = PATTERN_CONGESTION; - break; - default: - pattern = PATTERN_HANGUP; - } - - return pattern; -} - -enum process_state { - PROCESS_IDLE = 0, /* IDLE */ - PROCESS_SETUP_RO, /* call from radio to MNCC */ - PROCESS_SETUP_RT, /* call from MNCC to radio */ - PROCESS_ALERTING_RO, /* call from radio to MNCC */ - PROCESS_ALERTING_RT, /* call from MNCC to radio */ - PROCESS_CONNECT, - PROCESS_DISCONNECT, -}; - -/* MNCC call instance */ -typedef struct process { - struct process *next; - int callref; - enum process_state state; - int audio_disconnected; /* if not associated with transceiver anymore */ - enum audio_pattern pattern; - int audio_pos; - uint8_t cause; - struct timer timer; -} process_t; - -static process_t *process_head = NULL; - -static void process_timeout(struct timer *timer); - -static process_t *create_process(int callref, enum process_state state) -{ - process_t *process; - - process = calloc(sizeof(*process), 1); - if (!process) { - PDEBUG(DCALL, DEBUG_ERROR, "No memory!\n"); - abort(); - } - timer_init(&process->timer, process_timeout, process); - process->next = process_head; - process_head = process; - - process->callref = callref; - process->state = state; - - return process; -} - -static void destroy_process(int callref) -{ - process_t *process = process_head; - process_t **process_p = &process_head; - - while (process) { - if (process->callref == callref) { - *process_p = process->next; - timer_exit(&process->timer); - free(process); - return; - } - process_p = &process->next; - process = process->next; - } - PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref); -} - -static process_t *get_process(int callref) -{ - process_t *process = process_head; - - while (process) { - if (process->callref == callref) - return process; - process = process->next; - } - return NULL; -} - -static void new_state_process(int callref, enum process_state state) -{ - process_t *process = get_process(callref); - - if (!process) { - PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref); - return; - } - process->state = state; -} - -static void set_pattern_process(int callref, enum audio_pattern pattern) -{ - process_t *process = get_process(callref); - - if (!process) { - PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref); - return; - } - process->pattern = pattern; - process->audio_pos = 0; -} - -/* disconnect audio, now send audio directly from pattern/announcement, not from transceiver */ -static void disconnect_process(int callref, int cause) -{ - process_t *process = get_process(callref); - - if (!process) { - PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref); - return; - } - process->pattern = cause2pattern(cause); - process->audio_disconnected = 1; - process->audio_pos = 0; - process->cause = cause; - timer_start(&process->timer, DISC_TIMEOUT); -} - -static void get_process_patterns(process_t *process, int16_t *samples, int length) -{ - const int16_t *spl; - int size, max, pos; - - get_pattern(&spl, &size, &max, process->pattern); - - /* stream sample */ - pos = process->audio_pos; - while(length--) { - if (pos >= size) - *samples++ = 0; - else - *samples++ = spl[pos] >> 1; - if (++pos == max) - pos = 0; - } - process->audio_pos = pos; -} - -static void process_timeout(struct timer *timer) -{ - process_t *process = (process_t *)timer->priv; - - { - /* announcement timeout */ - uint8_t buf[sizeof(struct gsm_mncc)]; - struct gsm_mncc *mncc = (struct gsm_mncc *)buf; - - memset(buf, 0, sizeof(buf)); - mncc->msg_type = MNCC_REL_IND; - mncc->callref = process->callref; - mncc->fields |= MNCC_F_CAUSE; - mncc->cause.location = LOCATION_PRIVATE_LOCAL; - mncc->cause.value = process->cause; - - destroy_process(process->callref); - PDEBUG(DCALL, DEBUG_INFO, "Releasing MNCC call towards fixed network (after timeout)\n"); - mncc_up(buf, sizeof(struct gsm_mncc)); - } -} - -int call_init(int _send_patterns, int _release_on_disconnect) -{ - send_patterns = _send_patterns; - release_on_disconnect = _release_on_disconnect; - - return 0; -} - -/* Setup is received from transceiver. */ -static int _indicate_setup(int callref, const char *callerid, const char *dialing) -{ - uint8_t buf[sizeof(struct gsm_mncc)]; - struct gsm_mncc *mncc = (struct gsm_mncc *)buf; - int rc; - - memset(buf, 0, sizeof(buf)); - mncc->msg_type = MNCC_SETUP_IND; - mncc->callref = callref; - mncc->fields |= MNCC_F_CALLING; - if (callerid) { - strncpy(mncc->calling.number, callerid, sizeof(mncc->calling.number) - 1); - mncc->calling.type = 4; /* caller ID is of type 'subscriber' */ - } // otherwise unknown and no number - mncc->fields |= MNCC_F_CALLED; - strncpy(mncc->called.number, dialing, sizeof(mncc->called.number) - 1); - mncc->called.type = 0; /* dialing is of type 'unknown' */ - mncc->lchan_type = GSM_LCHAN_TCH_F; - mncc->fields |= MNCC_F_BEARER_CAP; - mncc->bearer_cap.speech_ver[0] = BCAP_ANALOG_8000HZ; - mncc->bearer_cap.speech_ver[1] = -1; - - PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC setup towards fixed network\n"); - rc = mncc_up(buf, sizeof(struct gsm_mncc)); - if (rc < 0) - destroy_process(callref); - return rc; -} -int call_up_setup(int callref, const char *callerid, const char *dialing) -{ - int rc; - - if (!callref) { - PDEBUG(DCALL, DEBUG_DEBUG, "Ignoring setup, because callref not set. (not for us)\n"); - return -CAUSE_INVALCALLREF; - } - - if (callref < 0x4000000) { - PDEBUG(DCALL, DEBUG_ERROR, "Invalid callref from mobile station, please fix!\n"); - abort(); - } - - PDEBUG(DCALL, DEBUG_INFO, "Incoming call from '%s' to '%s'\n", callerid ? : "unknown", dialing); - if (!strcmp(dialing, "010")) - PDEBUG(DCALL, DEBUG_INFO, " -> Call to Operator '%s'\n", dialing); - - - create_process(callref, PROCESS_SETUP_RO); - - rc = _indicate_setup(callref, callerid, dialing); - - return rc; -} - -/* Transceiver indicates alerting. */ -static void _indicate_alerting(int callref) -{ - uint8_t buf[sizeof(struct gsm_mncc)]; - struct gsm_mncc *mncc = (struct gsm_mncc *)buf; - int rc; - - memset(buf, 0, sizeof(buf)); - mncc->msg_type = MNCC_ALERT_IND; - mncc->callref = callref; - - PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC alerting towards fixed network\n"); - rc = mncc_up(buf, sizeof(struct gsm_mncc)); - if (rc < 0) - destroy_process(callref); -} -void call_up_alerting(int callref) -{ - if (!callref) { - PDEBUG(DCALL, DEBUG_DEBUG, "Ignoring alerting, because callref not set. (not for us)\n"); - return; - } - - PDEBUG(DCALL, DEBUG_INFO, "Call is alerting\n"); - - if (!send_patterns) - _indicate_alerting(callref); - set_pattern_process(callref, PATTERN_RINGBACK); - new_state_process(callref, PROCESS_ALERTING_RT); -} - -/* Transceiver indicates answer. */ -static void _indicate_answer(int callref, const char *connect_id) -{ - uint8_t buf[sizeof(struct gsm_mncc)]; - struct gsm_mncc *mncc = (struct gsm_mncc *)buf; - int rc; - - memset(buf, 0, sizeof(buf)); - mncc->msg_type = MNCC_SETUP_CNF; - mncc->callref = callref; - mncc->fields |= MNCC_F_CONNECTED; - /* copy connected number as subscriber number */ - strncpy(mncc->connected.number, connect_id, sizeof(mncc->connected.number)); - mncc->connected.type = 4; - mncc->connected.plan = 1; - mncc->connected.present = 0; - mncc->connected.screen = 3; - - PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC answer towards fixed network\n"); - rc = mncc_up(buf, sizeof(struct gsm_mncc)); - if (rc < 0) - destroy_process(callref); -} -void call_up_answer(int callref, const char *connect_id) -{ - if (!callref) { - PDEBUG(DCALL, DEBUG_DEBUG, "Ignoring answer, because callref not set. (not for us)\n"); - return; - } - - PDEBUG(DCALL, DEBUG_INFO, "Call has been answered by '%s'\n", connect_id); - - if (!send_patterns) - _indicate_answer(callref, connect_id); - set_pattern_process(callref, PATTERN_NONE); - new_state_process(callref, PROCESS_CONNECT); -} - -/* Transceiver indicates release. */ -static void _indicate_disconnect_release(int callref, int cause, int disc) -{ - uint8_t buf[sizeof(struct gsm_mncc)]; - struct gsm_mncc *mncc = (struct gsm_mncc *)buf; - int rc; - - memset(buf, 0, sizeof(buf)); - mncc->msg_type = (disc) ? MNCC_DISC_IND : MNCC_REL_IND; - mncc->callref = callref; - mncc->fields |= MNCC_F_CAUSE; - mncc->cause.location = LOCATION_PRIVATE_LOCAL; - mncc->cause.value = cause; - - PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC %s towards fixed network\n", (disc) ? "disconnect" : "release"); - rc = mncc_up(buf, sizeof(struct gsm_mncc)); - if (rc < 0) - destroy_process(callref); -} -void call_up_release(int callref, int cause) -{ - process_t *process; - - if (!callref) { - PDEBUG(DCALL, DEBUG_DEBUG, "Ignoring release, because callref not set. (not for us)\n"); - return; - } - - PDEBUG(DCALL, DEBUG_INFO, "Call has been released with cause=%d\n", cause); - - process = get_process(callref); - if (process) { - /* just keep MNCC connection if tones shall be sent. - * no tones while setting up / alerting the call. */ - if (send_patterns - && process->state != PROCESS_SETUP_RO - && process->state != PROCESS_ALERTING_RO) - disconnect_process(callref, cause); - else - /* if no tones shall be sent, release on disconnect - * or RO setup states */ - if (process->state == PROCESS_DISCONNECT - || process->state == PROCESS_SETUP_RO - || process->state == PROCESS_ALERTING_RO) { - destroy_process(callref); - _indicate_disconnect_release(callref, cause, 0); - /* if no tones shall be sent, disconnect on all other states */ - } else { - disconnect_process(callref, cause); - _indicate_disconnect_release(callref, cause, 1); - } - } else { - /* we don't know about the process, just send release to upper layer anyway */ - _indicate_disconnect_release(callref, cause, 0); - } -} - -/* turn recall tone on or off */ -void call_tone_recall(int callref, int on) -{ - set_pattern_process(callref, (on) ? PATTERN_RECALL : PATTERN_NONE); -} - -/* forward audio to MNCC or call instance */ -void call_up_audio(int callref, sample_t *samples, int count) -{ - if (count != 160) { - fprintf(stderr, "Samples must be 160, please fix!\n"); - abort(); - } - /* is MNCC us used, forward audio */ - uint8_t buf[sizeof(struct gsm_data_frame) + 160 * sizeof(int16_t)]; - struct gsm_data_frame *data = (struct gsm_data_frame *)buf; - process_t *process; - - if (!callref) - return; - - /* if we are disconnected, ignore audio */ - process = get_process(callref); - if (!process || process->pattern != PATTERN_NONE) - return; - - /* forward audio */ - data->msg_type = ANALOG_8000HZ; - data->callref = callref; -#ifdef DEBUG_LEVEL - double lev = level_of(samples, count); - printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev))); -#endif - samples_to_int16((int16_t *)data->data, samples, count); - - mncc_up(buf, sizeof(buf)); - /* don't destroy process here in case of an error */ -} - -/* clock that is used to transmit patterns */ -void call_clock(void) -{ - process_t *process = process_head; - uint8_t buf[sizeof(struct gsm_data_frame) + 160 * sizeof(int16_t)]; - struct gsm_data_frame *data = (struct gsm_data_frame *)buf; - - while(process) { - if (process->pattern != PATTERN_NONE) { - data->msg_type = ANALOG_8000HZ; - data->callref = process->callref; - /* try to get patterns, else copy the samples we got */ - get_process_patterns(process, (int16_t *)data->data, 160); -#ifdef DEBUG_LEVEL - sample_t samples[160]; - int16_to_samples(samples, (int16_t *)data->data, 160); - double lev = level_of(samples, 160); - printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev))); - samples_to_int16((int16_t *)data->data, samples, 160); -#endif - mncc_up(buf, sizeof(buf)); - /* don't destroy process here in case of an error */ - } - process = process->next; - } -} - -/* mncc messages received from fixed network */ -void mncc_down(uint8_t *buf, int length) -{ - struct gsm_mncc *mncc = (struct gsm_mncc *)buf; - char number[sizeof(mncc->called.number)]; - char caller_id[sizeof(mncc->calling.number)]; - enum number_type caller_type; - int callref; - int rc; - process_t *process; - - callref = mncc->callref; - process = get_process(callref); - if (!process) { - if (mncc->msg_type == MNCC_SETUP_REQ) - process = create_process(callref, PROCESS_SETUP_RT); - else { - if (mncc->msg_type != MNCC_REL_REQ) - PDEBUG(DCALL, DEBUG_ERROR, "No process!\n"); - return; - } - } - - if (mncc->msg_type == ANALOG_8000HZ) { - struct gsm_data_frame *data = (struct gsm_data_frame *)buf; - sample_t samples[160]; - - /* if we are disconnected, ignore audio */ - if (process->pattern != PATTERN_NONE) - return; - int16_to_samples(samples, (int16_t *)data->data, 160); -#ifdef DEBUG_LEVEL - double lev = level_of(samples, 160); - printf("festnetz-level: %s %.4f\n", debug_db(lev), (20 * log10(lev))); -#endif - call_down_audio(callref, samples, 160); - return; - } - - if (process->audio_disconnected) { - switch(mncc->msg_type) { - case MNCC_DISC_REQ: - PDEBUG(DCALL, DEBUG_INFO, "Received MNCC disconnect from fixed network with cause %d\n", mncc->cause.value); - - PDEBUG(DCALL, DEBUG_INFO, "Call disconnected, releasing!\n"); - - destroy_process(callref); - - PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC release towards fixed network\n"); - mncc->msg_type = MNCC_REL_IND; - rc = mncc_up(buf, sizeof(struct gsm_mncc)); - if (rc < 0) - destroy_process(callref); - break; - case MNCC_REL_REQ: - PDEBUG(DCALL, DEBUG_INFO, "Received MNCC release from fixed network with cause %d\n", mncc->cause.value); - - PDEBUG(DCALL, DEBUG_INFO, "Call released\n"); - - destroy_process(callref); - break; - } - return; - } - - switch(mncc->msg_type) { - case MNCC_SETUP_REQ: - strcpy(number, mncc->called.number); - - /* caller ID conversion */ - strcpy(caller_id, mncc->calling.number); - switch(mncc->calling.type) { - case 1: - caller_type = TYPE_INTERNATIONAL; - break; - case 2: - caller_type = TYPE_NATIONAL; - break; - case 4: - caller_type = TYPE_SUBSCRIBER; - break; - default: /* or 0 */ - caller_type = TYPE_UNKNOWN; - break; - } - if (!caller_id[0]) - caller_type = TYPE_NOTAVAIL; - if (mncc->calling.present == 1) - caller_type = TYPE_ANONYMOUS; - - PDEBUG(DCALL, DEBUG_INFO, "Received MNCC call from fixed network '%s' to mobile '%s'\n", caller_id, number); - - if (mncc->callref >= 0x4000000) { - fprintf(stderr, "Invalid callref from fixed network, please fix!\n"); - abort(); - } - - PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC call confirm towards fixed network\n"); - memset(buf, 0, length); - mncc->msg_type = MNCC_CALL_CONF_IND; - mncc->callref = callref; - mncc->lchan_type = GSM_LCHAN_TCH_F; - mncc->fields |= MNCC_F_BEARER_CAP; - mncc->bearer_cap.speech_ver[0] = BCAP_ANALOG_8000HZ; - mncc->bearer_cap.speech_ver[1] = -1; - - mncc_up(buf, sizeof(struct gsm_mncc)); - - PDEBUG(DCALL, DEBUG_INFO, "Outgoing call from '%s' to '%s'\n", caller_id, number); - - rc = call_down_setup(callref, caller_id, caller_type, number); - if (rc < 0) { - PDEBUG(DCALL, DEBUG_NOTICE, "Call rejected, cause %d\n", -rc); - if (send_patterns) { - PDEBUG(DCALL, DEBUG_DEBUG, "Early connecting after setup\n"); - _indicate_answer(callref, number); - } else { - PDEBUG(DCALL, DEBUG_INFO, "Disconnecting MNCC call towards fixed network (cause=%d)\n", -rc); - _indicate_disconnect_release(callref, -rc, 1); - } - disconnect_process(callref, -rc); - break; - } - - if (send_patterns) { - PDEBUG(DCALL, DEBUG_DEBUG, "Early connecting after setup\n"); - _indicate_answer(callref, number); - break; - } - break; - case MNCC_ALERT_REQ: - PDEBUG(DCALL, DEBUG_INFO, "Received MNCC alerting from fixed network\n"); - new_state_process(callref, PROCESS_ALERTING_RO); - break; - case MNCC_SETUP_RSP: - PDEBUG(DCALL, DEBUG_INFO, "Received MNCC answer from fixed network\n"); - new_state_process(callref, PROCESS_CONNECT); - PDEBUG(DCALL, DEBUG_INFO, "Call answered\n"); - call_down_answer(callref); - PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC setup complete towards fixed network\n"); - memset(buf, 0, length); - mncc->msg_type = MNCC_SETUP_COMPL_IND; - mncc->callref = callref; - rc = mncc_up(buf, sizeof(struct gsm_mncc)); - if (rc < 0) - destroy_process(callref); - break; - case MNCC_DISC_REQ: - PDEBUG(DCALL, DEBUG_INFO, "Received MNCC disconnect from fixed network with cause %d\n", mncc->cause.value); - - process = get_process(callref); - if (process && process->state == PROCESS_CONNECT && release_on_disconnect) { - PDEBUG(DCALL, DEBUG_INFO, "Releasing, because we don't send disconnect tones to mobile phone\n"); - - PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC release towards fixed network\n"); - mncc->msg_type = MNCC_REL_IND; - mncc_up(buf, sizeof(struct gsm_mncc)); - goto release; - } - new_state_process(callref, PROCESS_DISCONNECT); - PDEBUG(DCALL, DEBUG_INFO, "Call disconnected\n"); - call_down_disconnect(callref, mncc->cause.value); - break; - case MNCC_REL_REQ: - PDEBUG(DCALL, DEBUG_INFO, "Received MNCC release from fixed network with cause %d\n", mncc->cause.value); - -release: - destroy_process(callref); - PDEBUG(DCALL, DEBUG_INFO, "Call released\n"); - call_down_release(callref, mncc->cause.value); - break; - } -} - -int (*mncc_up)(uint8_t *buf, int length) = NULL; - -/* break down of MNCC socket */ -void mncc_flush(void) -{ - while(process_head) { - PDEBUG(DCALL, DEBUG_NOTICE, "MNCC socket closed, releasing call\n"); - call_down_release(process_head->callref, CAUSE_TEMPFAIL); - destroy_process(process_head->callref); - /* note: callref is released by sender's instance */ - } -} - |