From 051cc81b139bd553158a87a26dc49563f5f1ec6b Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 12 Jun 2016 10:50:11 +0200 Subject: [PATCH] C-Netz: Move transaction routines to seperate file --- src/cnetz/Makefile.am | 1 + src/cnetz/cnetz.c | 242 ++++------------------------------------ src/cnetz/cnetz.h | 42 +------ src/cnetz/telegramm.c | 9 -- src/cnetz/telegramm.h | 1 - src/cnetz/transaction.c | 225 +++++++++++++++++++++++++++++++++++++ src/cnetz/transaction.h | 53 +++++++++ 7 files changed, 303 insertions(+), 270 deletions(-) create mode 100644 src/cnetz/transaction.c create mode 100644 src/cnetz/transaction.h diff --git a/src/cnetz/Makefile.am b/src/cnetz/Makefile.am index 3b40ad9..c4f4d30 100644 --- a/src/cnetz/Makefile.am +++ b/src/cnetz/Makefile.am @@ -5,6 +5,7 @@ bin_PROGRAMS = \ cnetz_SOURCES = \ cnetz.c \ + transaction.c \ database.c \ sysinfo.c \ telegramm.c \ diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c index 07ae2e4..8d0b3c5 100644 --- a/src/cnetz/cnetz.c +++ b/src/cnetz/cnetz.c @@ -105,11 +105,6 @@ int cnetz_init(void) } static void cnetz_go_idle(cnetz_t *cnetz); -static transaction_t *create_transaction(cnetz_t *cnetz, uint32_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest); -static transaction_t *search_transaction(cnetz_t *cnetz, uint32_t state_mask); -static void destroy_transaction(transaction_t *trans); -static void trans_new_state(transaction_t *trans, int state); -static void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans); /* Create transceiver instance and link to a list. */ int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev, int samplerate, int cross_channels, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, double noise, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, int loopback) @@ -270,13 +265,13 @@ void cnetz_destroy(sender_t *sender) static void cnetz_go_idle(cnetz_t *cnetz) { if (cnetz->sender.callref) { - PDEBUG(DBNETZ, DEBUG_ERROR, "Releasing missing callref, please fix!\n"); + PDEBUG(DCNETZ, DEBUG_ERROR, "Releasing but still having callref, please fix!\n"); call_in_release(cnetz->sender.callref, CAUSE_NORMAL); cnetz->sender.callref = 0; } /* set scheduler to OgK */ - PDEBUG(DBNETZ, DEBUG_INFO, "Entering IDLE state on channel %d.\n", cnetz->sender.kanal); + PDEBUG(DCNETZ, DEBUG_INFO, "Entering IDLE state on channel %d.\n", cnetz->sender.kanal); cnetz_new_state(cnetz, CNETZ_IDLE); if (cnetz->dsp_mode == DSP_MODE_SPK_K || cnetz->dsp_mode == DSP_MODE_SPK_V) { /* go idle after next frame/slot */ @@ -396,13 +391,7 @@ inval: for (sender = sender_head; sender; sender = sender->next) { cnetz = (cnetz_t *) sender; /* search transaction for this number */ - trans = cnetz->trans_list; - for (trans = cnetz->trans_list; trans; trans = trans->next) { - if (trans->futln_nat == futln_nat - && trans->futln_fuvst == futln_fuvst - && trans->futln_rest == futln_rest) - break; - } + trans = search_transaction_number(cnetz, futln_nat, futln_fuvst, futln_rest); if (trans) break; } @@ -462,12 +451,15 @@ void call_out_disconnect(int callref, int cause) return; } +#if 0 + dont use this, because busy state is only entered when channel is actually used for voice if (cnetz->state != CNETZ_BUSY) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing release, but sender is not in busy state.\n"); + PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing disconnect, but sender is not in busy state.\n"); call_in_release(callref, cause); sender->callref = 0; return; } +#endif trans = cnetz->trans_list; if (!trans) { @@ -484,16 +476,17 @@ void call_out_disconnect(int callref, int cause) case DSP_MODE_SPK_K: PDEBUG(DCNETZ, DEBUG_INFO, "Call control disconnects on speech channel, releasing towards mobile station.\n"); cnetz_release(trans, cnetz_cause_isdn2cnetz(cause)); + call_in_release(callref, cause); + sender->callref = 0; break; default: PDEBUG(DCNETZ, DEBUG_INFO, "Call control disconnects on organisation channel, removing transaction.\n"); + call_in_release(callref, cause); + sender->callref = 0; destroy_transaction(trans); cnetz_go_idle(cnetz); } - call_in_release(callref, cause); - - sender->callref = 0; } /* Call control releases call toward mobile station. */ @@ -518,10 +511,13 @@ void call_out_release(int callref, int cause) sender->callref = 0; +#if 0 + dont use this, because busy state is only entered when channel is actually used for voice if (cnetz->state != CNETZ_BUSY) { PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing release, but sender is not in busy state.\n"); return; } +#endif trans = cnetz->trans_list; if (!trans) @@ -559,192 +555,6 @@ int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_res return 0; } -/* - * Transaction handling - */ - -static void transaction_timeout(struct timer *timer); - -/* link transaction to list */ -static void link_transaction(transaction_t *trans, cnetz_t *cnetz) -{ - transaction_t **transp; - - /* attach to end of list, so first transaction is served first */ - trans->cnetz = cnetz; - transp = &cnetz->trans_list; - while (*transp) - transp = &((*transp)->next); - *transp = trans; -} - -/* create transaction */ -static transaction_t *create_transaction(cnetz_t *cnetz, uint32_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest) -{ - transaction_t *trans; - - /* search transaction for this subsriber */ - trans = cnetz->trans_list; - while (trans) { - if (trans->futln_nat == futln_nat - && trans->futln_fuvst == futln_fuvst - && trans->futln_rest == futln_rest) { - const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DCNETZ, DEBUG_NOTICE, "Found alredy pending transaction for subscriber '%s', deleting!\n", rufnummer); - destroy_transaction(trans); - break; - } - trans = trans->next; - } - - trans = calloc(1, sizeof(*trans)); - if (!trans) { - PDEBUG(DCNETZ, DEBUG_ERROR, "No memory!\n"); - return NULL; - } - - timer_init(&trans->timer, transaction_timeout, trans); - - trans_new_state(trans, state); - trans->futln_nat = futln_nat; - trans->futln_fuvst = futln_fuvst; - trans->futln_rest = futln_rest; - - if (state == TRANS_VWG) - trans->mo_call = 1; - if (state == TRANS_VAK) - trans->mt_call = 1; - - const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DCNETZ, DEBUG_INFO, "Created transaction for subscriber '%s'\n", rufnummer); - - link_transaction(trans, cnetz); - - /* update database: now busy */ - update_db(cnetz, futln_nat, futln_fuvst, futln_rest, 1, 0); - - return trans; -} - -/* unlink transaction from list */ -static void unlink_transaction(transaction_t *trans) -{ - transaction_t **transp; - - /* unlink */ - transp = &trans->cnetz->trans_list; - while (*transp && *transp != trans) - transp = &((*transp)->next); - if (!(*transp)) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Transaction not in list, please fix!!\n"); - abort(); - } - *transp = trans->next; - trans->cnetz = NULL; -} - -/* destroy transaction */ -static void destroy_transaction(transaction_t *trans) -{ - /* update database: now idle */ - update_db(trans->cnetz, trans->futln_nat, trans->futln_fuvst, trans->futln_rest, 0, trans->ma_failed); - - unlink_transaction(trans); - - const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DCNETZ, DEBUG_INFO, "Destroying transaction for subscriber '%s'\n", rufnummer); - - timer_exit(&trans->timer); - - trans_new_state(trans, 0); - - free(trans); -} - -static transaction_t *search_transaction(cnetz_t *cnetz, uint32_t state_mask) -{ - transaction_t *trans = cnetz->trans_list; - - while (trans) { - if ((trans->state & state_mask)) { - const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DCNETZ, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); - return trans; - } - trans = trans->next; - } - - return NULL; -} - -static transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest) -{ - transaction_t *trans = cnetz->trans_list; - - while (trans) { - if (trans->futln_nat == futln_nat - && trans->futln_fuvst == futln_fuvst - && trans->futln_rest == futln_rest) { - const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DCNETZ, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); - return trans; - } - trans = trans->next; - } - - return NULL; -} - -static const char *trans_state_name(int state) -{ - switch (state) { - case 0: - return "IDLE"; - case TRANS_EM: - return "EM"; - case TRANS_UM: - return "UM"; - case TRANS_MA: - return "MA"; - case TRANS_MFT: - return "MFT"; - case TRANS_VWG: - return "VWG"; - case TRANS_WAF: - return "WAF"; - case TRANS_WBP: - return "WBP"; - case TRANS_WBN: - return "WBN"; - case TRANS_VAG: - return "VAG"; - case TRANS_VAK: - return "VAK"; - case TRANS_BQ: - return "BQ"; - case TRANS_VHQ: - return "VHQ"; - case TRANS_RTA: - return "RTA"; - case TRANS_DS: - return "DS"; - case TRANS_AHQ: - return "AHQ"; - case TRANS_AF: - return "AF"; - case TRANS_AT: - return "AT"; - default: - return ""; - } -} - -static void trans_new_state(transaction_t *trans, int state) -{ - PDEBUG(DCNETZ, DEBUG_INFO, "Transaction state %s -> %s\n", trans_state_name(trans->state), trans_state_name(state)); - trans->state = state; -} - static struct cnetz_channels { enum cnetz_chan_type chan_type; const char *short_name; @@ -805,7 +615,7 @@ const char *chan_type_long_name(enum cnetz_chan_type chan_type) } /* Timeout handling */ -static void transaction_timeout(struct timer *timer) +void transaction_timeout(struct timer *timer) { transaction_t *trans = (transaction_t *)timer->priv; cnetz_t *cnetz = trans->cnetz; @@ -868,20 +678,6 @@ static void transaction_timeout(struct timer *timer) } } -static void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans) -{ - /* flush after this very trans */ - while (trans->next) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Kicking other pending transaction\n"); - destroy_transaction(trans); - } - /* flush before this very trans */ - while (cnetz->trans_list != trans) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Kicking other pending transaction\n"); - destroy_transaction(cnetz->trans_list); - } -} - /* * sync to phone * @@ -1001,10 +797,18 @@ wbn: timer_start(&trans->timer, 0.150 + 0.0375 * F_BQ); /* two slots + F_BQ frames */ /* select channel */ spk = search_free_spk(); + if (!spk) { + PDEBUG(DCNETZ, DEBUG_NOTICE, "No free channel anymore, kicking transaction due to race condition!\n"); + destroy_transaction(trans); + cnetz_go_idle(cnetz); + break; + } if (spk == cnetz) { PDEBUG(DCNETZ, DEBUG_INFO, "Staying on combined calling + traffic channel %d\n", spk->sender.kanal); } else { PDEBUG(DCNETZ, DEBUG_INFO, "Assigning phone to traffic channel %d\n", spk->sender.kanal); + spk->sender.callref = cnetz->sender.callref; + cnetz->sender.callref = 0; /* sync RX time to current OgK time */ spk->fsk_demod.bit_time = cnetz->fsk_demod.bit_time; } diff --git a/src/cnetz/cnetz.h b/src/cnetz/cnetz.h index f61b664..59b18ea 100644 --- a/src/cnetz/cnetz.h +++ b/src/cnetz/cnetz.h @@ -2,6 +2,7 @@ #include "../common/sender.h" #include "fsk_fm_demod.h" #include "scrambler.h" +#include "transaction.h" #define CNETZ_OGK_KANAL 131 @@ -27,31 +28,6 @@ enum cnetz_state { CNETZ_BUSY, /* currently processing a call, no other transaction allowed */ }; - /* login to the network */ -#define TRANS_EM (1 << 0) /* attach request received, sending reply */ - /* roaming to different base station/network */ -#define TRANS_UM (1 << 1) /* roaming request received, sending reply */ - /* check if phone is still on */ -#define TRANS_MA (1 << 2) /* periodic online check, waiting for time slot to send order */ -#define TRANS_MFT (1 << 3) /* periodic online check sent, waiting for reply */ - /* mobile originated call */ -#define TRANS_VWG (1 << 4) /* received dialing request, waiting for time slot to send dial order */ -#define TRANS_WAF (1 << 5) /* dial order sent, waiting for dialing */ -#define TRANS_WBP (1 << 6) /* dialing received, waiting for time slot to acknowledge call */ -#define TRANS_WBN (1 << 7) /* dialing received, waiting for time slot to reject call */ -#define TRANS_VAG (1 << 8) /* establishment of call sent, switching channel */ - /* mobile terminated call */ -#define TRANS_VAK (1 << 9) /* establishment of call sent, switching channel */ - /* traffic channel */ -#define TRANS_BQ (1 << 10) /* accnowledge channel */ -#define TRANS_VHQ (1 << 11) /* hold call */ -#define TRANS_RTA (1 << 12) /* hold call and make the phone ring */ -#define TRANS_DS (1 << 13) /* establish speech connection */ -#define TRANS_AHQ (1 << 14) /* establish speech connection after answer */ - /* release */ -#define TRANS_AF (1 << 15) /* release connection by base station */ -#define TRANS_AT (1 << 16) /* release connection by mobile station */ - /* timers */ #define F_BQ 8 /* number of not received frames at BQ state */ #define F_VHQK 16 /* number of not received frames at VHQ state during concentrated signalling */ @@ -69,22 +45,6 @@ enum cnetz_state { struct cnetz; struct telegramm; -typedef struct transaction { - struct transaction *next; /* pointer to next node in list */ - struct cnetz *cnetz; /* pointer to cnetz instance */ - uint8_t futln_nat; /* current station ID (3 values) */ - uint8_t futln_fuvst; - uint16_t futln_rest; - char dialing[17]; /* number dialed by the phone */ - int32_t state; /* state of transaction */ - int8_t release_cause; /* reason for release, (c-netz coding) */ - int count; /* counts resending things */ - struct timer timer; /* for varous timeouts */ - int mo_call; /* flags a moile originating call */ - int mt_call; /* flags a moile terminating call */ - int ma_failed; /* failed to get a response from MS */ -} transaction_t; - struct clock_speed { double meas_ti; /* time stamp for measurement interval */ double start_ti[4]; /* time stamp for start of counting */ diff --git a/src/cnetz/telegramm.c b/src/cnetz/telegramm.c index f5fdf07..5281089 100644 --- a/src/cnetz/telegramm.c +++ b/src/cnetz/telegramm.c @@ -457,15 +457,6 @@ const char *telegramm2rufnummer(telegramm_t *telegramm) return rufnummer; } -const char *transaction2rufnummer(transaction_t *trans) -{ - static char rufnummer[9]; - - sprintf(rufnummer, "%d%d%05d", trans->futln_nat, trans->futln_fuvst, trans->futln_rest); - - return rufnummer; -} - static void decode_dialstring(char *number, uint64_t value) { int index, max, shift; diff --git a/src/cnetz/telegramm.h b/src/cnetz/telegramm.h index 7f4566b..672bbd2 100644 --- a/src/cnetz/telegramm.h +++ b/src/cnetz/telegramm.h @@ -119,7 +119,6 @@ int init_coding(void); const char *telegramm_name(uint8_t opcode); const char *telegramm2rufnummer(telegramm_t *telegramm); -const char *transaction2rufnummer(transaction_t *trans); int match_fuz(cnetz_t *cnetz, telegramm_t *telegramm, int cell); int match_futln(telegramm_t *telegramm, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest); diff --git a/src/cnetz/transaction.c b/src/cnetz/transaction.c new file mode 100644 index 0000000..c8bf884 --- /dev/null +++ b/src/cnetz/transaction.c @@ -0,0 +1,225 @@ +/* C-Netz transaction handling + * + * (C) 2016 by Andreas Eversberg + * 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 . + */ + +#include +#include +#include +#include "../common/debug.h" +#include "../common/timer.h" +#include "cnetz.h" +#include "telegramm.h" +#include "database.h" + +const char *transaction2rufnummer(transaction_t *trans) +{ + static char rufnummer[9]; + + sprintf(rufnummer, "%d%d%05d", trans->futln_nat, trans->futln_fuvst, trans->futln_rest); + + return rufnummer; +} + +/* create transaction */ +transaction_t *create_transaction(cnetz_t *cnetz, uint32_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest) +{ + transaction_t *trans; + + /* search transaction for this subsriber */ + trans = search_transaction_number(cnetz, futln_nat, futln_fuvst, futln_rest); + if (trans) { + const char *rufnummer = transaction2rufnummer(trans); + PDEBUG(DTRANS, DEBUG_NOTICE, "Found alredy pending transaction for subscriber '%s', deleting!\n", rufnummer); + destroy_transaction(trans); + } + + trans = calloc(1, sizeof(*trans)); + if (!trans) { + PDEBUG(DTRANS, DEBUG_ERROR, "No memory!\n"); + return NULL; + } + + timer_init(&trans->timer, transaction_timeout, trans); + + trans_new_state(trans, state); + trans->futln_nat = futln_nat; + trans->futln_fuvst = futln_fuvst; + trans->futln_rest = futln_rest; + + if (state == TRANS_VWG) + trans->mo_call = 1; + if (state == TRANS_VAK) + trans->mt_call = 1; + + const char *rufnummer = transaction2rufnummer(trans); + PDEBUG(DTRANS, DEBUG_INFO, "Created transaction for subscriber '%s'\n", rufnummer); + + link_transaction(trans, cnetz); + + /* update database: now busy */ + update_db(cnetz, futln_nat, futln_fuvst, futln_rest, 1, 0); + + return trans; +} + +/* destroy transaction */ +void destroy_transaction(transaction_t *trans) +{ + /* update database: now idle */ + update_db(trans->cnetz, trans->futln_nat, trans->futln_fuvst, trans->futln_rest, 0, trans->ma_failed); + + unlink_transaction(trans); + + const char *rufnummer = transaction2rufnummer(trans); + PDEBUG(DTRANS, DEBUG_INFO, "Destroying transaction for subscriber '%s'\n", rufnummer); + + timer_exit(&trans->timer); + + trans_new_state(trans, 0); + + free(trans); +} + +/* link transaction to list */ +void link_transaction(transaction_t *trans, cnetz_t *cnetz) +{ + transaction_t **transp; + + /* attach to end of list, so first transaction is served first */ + trans->cnetz = cnetz; + transp = &cnetz->trans_list; + while (*transp) + transp = &((*transp)->next); + *transp = trans; +} + +/* unlink transaction from list */ +void unlink_transaction(transaction_t *trans) +{ + transaction_t **transp; + + /* unlink */ + transp = &trans->cnetz->trans_list; + while (*transp && *transp != trans) + transp = &((*transp)->next); + if (!(*transp)) { + PDEBUG(DTRANS, DEBUG_ERROR, "Transaction not in list, please fix!!\n"); + abort(); + } + *transp = trans->next; + trans->cnetz = NULL; +} + +transaction_t *search_transaction(cnetz_t *cnetz, uint32_t state_mask) +{ + transaction_t *trans = cnetz->trans_list; + + while (trans) { + if ((trans->state & state_mask)) { + const char *rufnummer = transaction2rufnummer(trans); + PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); + return trans; + } + trans = trans->next; + } + + return NULL; +} + +transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest) +{ + transaction_t *trans = cnetz->trans_list; + + while (trans) { + if (trans->futln_nat == futln_nat + && trans->futln_fuvst == futln_fuvst + && trans->futln_rest == futln_rest) { + const char *rufnummer = transaction2rufnummer(trans); + PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); + return trans; + } + trans = trans->next; + } + + return NULL; +} + +static const char *trans_state_name(int state) +{ + switch (state) { + case 0: + return "IDLE"; + case TRANS_EM: + return "EM"; + case TRANS_UM: + return "UM"; + case TRANS_MA: + return "MA"; + case TRANS_MFT: + return "MFT"; + case TRANS_VWG: + return "VWG"; + case TRANS_WAF: + return "WAF"; + case TRANS_WBP: + return "WBP"; + case TRANS_WBN: + return "WBN"; + case TRANS_VAG: + return "VAG"; + case TRANS_VAK: + return "VAK"; + case TRANS_BQ: + return "BQ"; + case TRANS_VHQ: + return "VHQ"; + case TRANS_RTA: + return "RTA"; + case TRANS_DS: + return "DS"; + case TRANS_AHQ: + return "AHQ"; + case TRANS_AF: + return "AF"; + case TRANS_AT: + return "AT"; + default: + return ""; + } +} + +void trans_new_state(transaction_t *trans, int state) +{ + PDEBUG(DTRANS, DEBUG_INFO, "Transaction state %s -> %s\n", trans_state_name(trans->state), trans_state_name(state)); + trans->state = state; +} + +void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans) +{ + /* flush after this very trans */ + while (trans->next) { + PDEBUG(DTRANS, DEBUG_NOTICE, "Kicking other pending transaction\n"); + destroy_transaction(trans); + } + /* flush before this very trans */ + while (cnetz->trans_list != trans) { + PDEBUG(DTRANS, DEBUG_NOTICE, "Kicking other pending transaction\n"); + destroy_transaction(cnetz->trans_list); + } +} + diff --git a/src/cnetz/transaction.h b/src/cnetz/transaction.h new file mode 100644 index 0000000..7c88c74 --- /dev/null +++ b/src/cnetz/transaction.h @@ -0,0 +1,53 @@ + + /* login to the network */ +#define TRANS_EM (1 << 0) /* attach request received, sending reply */ + /* roaming to different base station/network */ +#define TRANS_UM (1 << 1) /* roaming request received, sending reply */ + /* check if phone is still on */ +#define TRANS_MA (1 << 2) /* periodic online check, waiting for time slot to send order */ +#define TRANS_MFT (1 << 3) /* periodic online check sent, waiting for reply */ + /* mobile originated call */ +#define TRANS_VWG (1 << 4) /* received dialing request, waiting for time slot to send dial order */ +#define TRANS_WAF (1 << 5) /* dial order sent, waiting for dialing */ +#define TRANS_WBP (1 << 6) /* dialing received, waiting for time slot to acknowledge call */ +#define TRANS_WBN (1 << 7) /* dialing received, waiting for time slot to reject call */ +#define TRANS_VAG (1 << 8) /* establishment of call sent, switching channel */ + /* mobile terminated call */ +#define TRANS_VAK (1 << 9) /* establishment of call sent, switching channel */ + /* traffic channel */ +#define TRANS_BQ (1 << 10) /* accnowledge channel */ +#define TRANS_VHQ (1 << 11) /* hold call */ +#define TRANS_RTA (1 << 12) /* hold call and make the phone ring */ +#define TRANS_DS (1 << 13) /* establish speech connection */ +#define TRANS_AHQ (1 << 14) /* establish speech connection after answer */ + /* release */ +#define TRANS_AF (1 << 15) /* release connection by base station */ +#define TRANS_AT (1 << 16) /* release connection by mobile station */ + +typedef struct transaction { + struct transaction *next; /* pointer to next node in list */ + cnetz_t *cnetz; /* pointer to cnetz instance */ + uint8_t futln_nat; /* current station ID (3 values) */ + uint8_t futln_fuvst; + uint16_t futln_rest; + char dialing[17]; /* number dialed by the phone */ + int32_t state; /* state of transaction */ + int8_t release_cause; /* reason for release, (c-netz coding) */ + int count; /* counts resending things */ + struct timer timer; /* for varous timeouts */ + int mo_call; /* flags a moile originating call */ + int mt_call; /* flags a moile terminating call */ + int ma_failed; /* failed to get a response from MS */ +} transaction_t; + +const char *transaction2rufnummer(transaction_t *trans); +transaction_t *create_transaction(cnetz_t *cnetz, uint32_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest); +void destroy_transaction(transaction_t *trans); +void link_transaction(transaction_t *trans, cnetz_t *cnetz); +void unlink_transaction(transaction_t *trans); +transaction_t *search_transaction(cnetz_t *cnetz, uint32_t state_mask); +transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest); +void trans_new_state(transaction_t *trans, int state); +void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans); +void transaction_timeout(struct timer *timer); +