diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c
index f0c3fa0..fc9f833 100644
--- a/src/cnetz/cnetz.c
+++ b/src/cnetz/cnetz.c
@@ -17,6 +17,15 @@
* along with this program. If not, see .
*/
+/* Notes on channel state an callref:
+ *
+ * If channel state is busy, it is used as SpK, also it has callref.
+ *
+ * Each transaction has callref, but callref is only assigned to channel
+ * in SpK mode, so voice frames are routed there.
+ *
+ */
+
#define CHAN cnetz->sender.kanal
#include
@@ -338,6 +347,7 @@ cnetz_t *search_free_spk(void)
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
+ /* ignore busy channel */
if (cnetz->state != CNETZ_IDLE)
continue;
/* return first free SpK */
@@ -358,7 +368,7 @@ cnetz_t *search_ogk(void)
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
- /* if callref is set, we ignore busy channel with this callref */
+ /* ignore busy channel */
if (cnetz->state != CNETZ_IDLE)
continue;
if (cnetz->chan_type == CHAN_TYPE_OGK)
@@ -436,14 +446,13 @@ inval:
PDEBUG(DCNETZ, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
/* 6. trying to page mobile station */
- cnetz->sender.callref = callref;
-
trans = create_transaction(cnetz, TRANS_VAK, dialing[0] - '0', dialing[1] - '0', atoi(dialing + 2));
if (!trans) {
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
sender->callref = 0;
return -CAUSE_TEMPFAIL;
}
+ trans->callref = callref;
trans->try = 1;
return 0;
@@ -463,7 +472,9 @@ void call_out_disconnect(int callref, int cause)
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
- if (sender->callref == callref)
+ /* search transaction for this callref */
+ trans = search_transaction_callref(cnetz, callref);
+ if (trans)
break;
}
if (!sender) {
@@ -482,12 +493,14 @@ void call_out_disconnect(int callref, int cause)
}
#endif
+#if 0
trans = cnetz->trans_list;
if (!trans) {
call_in_release(callref, cause);
sender->callref = 0;
return;
}
+#endif
/* Release when not active */
@@ -499,6 +512,7 @@ void call_out_disconnect(int callref, int cause)
cnetz_release(trans, cnetz_cause_isdn2cnetz(cause));
call_in_release(callref, cause);
sender->callref = 0;
+ trans->callref = 0;
break;
default:
PDEBUG(DCNETZ, DEBUG_INFO, "Call control disconnects on organisation channel, removing transaction.\n");
@@ -521,7 +535,9 @@ void call_out_release(int callref, int cause)
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
- if (sender->callref == callref)
+ /* search transaction for this callref */
+ trans = search_transaction_callref(cnetz, callref);
+ if (trans)
break;
}
if (!sender) {
@@ -531,6 +547,7 @@ void call_out_release(int callref, int cause)
}
sender->callref = 0;
+ trans->callref = 0;
#if 0
dont use this, because busy state is only entered when channel is actually used for voice
@@ -656,27 +673,18 @@ void transaction_timeout(struct timer *timer)
break;
case TRANS_BQ:
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after channel allocation 'Belegung Quittung'\n");
-#if 0
- if (trans->try == N) {
- if (trans->mt_call) {
- call_in_release(cnetz->sender.callref, CAUSE_OUTOFORDER);
- cnetz->sender.callref = 0;
- }
- cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
- break;
- }
-#endif
trans_new_state(trans, TRANS_AF);
trans->repeat = 0;
break;
case TRANS_VHQ:
if (cnetz->dsp_mode != DSP_MODE_SPK_V)
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response hile holding call 'Quittung Verbindung halten'\n");
+ PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response while holding call 'Quittung Verbindung halten'\n");
else
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Lost signal from 'FuTln' (mobile station)\n");
- if (trans->mt_call || trans->mo_call) {
- call_in_release(cnetz->sender.callref, CAUSE_TEMPFAIL);
+ if (trans->callref) {
+ call_in_release(trans->callref, CAUSE_TEMPFAIL);
cnetz->sender.callref = 0;
+ trans->callref = 0;
}
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
break;
@@ -684,18 +692,21 @@ void transaction_timeout(struct timer *timer)
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after connect 'Durchschalten'\n");
call_in_release(cnetz->sender.callref, CAUSE_TEMPFAIL);
cnetz->sender.callref = 0;
+ trans->callref = 0;
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
break;
case TRANS_RTA:
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after ringing order 'Rufton anschalten'\n");
call_in_release(cnetz->sender.callref, CAUSE_TEMPFAIL);
cnetz->sender.callref = 0;
+ trans->callref = 0;
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
break;
case TRANS_AHQ:
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after answer 'Abhebequittung'\n");
call_in_release(cnetz->sender.callref, CAUSE_TEMPFAIL);
cnetz->sender.callref = 0;
+ trans->callref = 0;
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
break;
case TRANS_MFT:
@@ -828,7 +839,7 @@ wbn:
/* select channel */
spk = search_free_spk();
if (!spk) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "No free channel anymore, kicking transaction due to race condition!\n");
+ PDEBUG(DCNETZ, DEBUG_NOTICE, "No free channel anymore, rejecting call!\n");
destroy_transaction(trans);
cnetz_go_idle(cnetz);
break;
@@ -837,8 +848,7 @@ wbn:
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;
+ spk->sender.callref = trans->callref;
/* sync RX time to current OgK time */
spk->fsk_demod.bit_time = cnetz->fsk_demod.bit_time;
}
@@ -1025,7 +1035,6 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz)
static telegramm_t telegramm;
transaction_t *trans = cnetz->trans_list;
cnetz_t *ogk;
- int callref;
memset(&telegramm, 0, sizeof(telegramm));
if (!trans)
@@ -1060,15 +1069,16 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz)
if (!cnetz->sender.loopback && (cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !timer_running(&trans->timer)) {
/* next sub frame */
if (trans->mo_call) {
- int callref = ++new_callref;
int rc;
- rc = call_in_setup(callref, transaction2rufnummer(trans), trans->dialing);
+ trans->callref = ++new_callref;
+ rc = call_in_setup(trans->callref, transaction2rufnummer(trans), trans->dialing);
if (rc < 0) {
PDEBUG(DCNETZ, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", -rc);
+ trans->callref = 0;
cnetz_release(trans, cnetz_cause_isdn2cnetz(-rc));
goto call_failed;
}
- cnetz->sender.callref = callref;
+ cnetz->sender.callref = trans->callref;
trans_new_state(trans, TRANS_DS);
trans->repeat = 0;
timer_start(&trans->timer, 0.0375 * F_DS); /* F_DS frames */
@@ -1077,7 +1087,7 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz)
trans_new_state(trans, TRANS_RTA);
timer_start(&trans->timer, 0.0375 * F_RTA); /* F_RTA frames */
trans->repeat = 0;
- call_in_alerting(cnetz->sender.callref);
+ call_in_alerting(trans->callref);
}
}
break;
@@ -1123,14 +1133,15 @@ call_failed:
}
if (trans->try == N) {
PDEBUG(DCNETZ, DEBUG_INFO, "Maximum retries, removing transaction\n");
- destroy_transaction(trans);
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
+ /* must destroy transaction after cnetz_release */
+ destroy_transaction(trans);
+ cnetz->sender.callref = 0;
cnetz_go_idle(cnetz);
break;
}
- /* remove call from SpK (or OgK) */
+ /* remove call from SpK (or OgK+SpK) */
unlink_transaction(trans);
- callref = cnetz->sender.callref;
cnetz->sender.callref = 0;
/* idle channel */
cnetz_go_idle(cnetz);
@@ -1138,13 +1149,13 @@ call_failed:
ogk = search_ogk();
if (!ogk) {
PDEBUG(DCNETZ, DEBUG_NOTICE, "Cannot retry, because currently no OgK available (busy)\n");
- destroy_transaction(trans);
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
+ /* must destroy transaction after cnetz_release */
+ destroy_transaction(trans);
break;
}
PDEBUG(DCNETZ, DEBUG_INFO, "Retry to assign channel.\n");
/* attach call to OgK */
- ogk->sender.callref = callref;
link_transaction(trans, ogk);
/* change state */
if (trans->mo_call)
@@ -1247,7 +1258,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
trans_new_state(trans, TRANS_AHQ);
trans->repeat = 0;
timer_stop(&trans->timer);
- call_in_answer(cnetz->sender.callref, transaction2rufnummer(trans));
+ call_in_answer(trans->callref, transaction2rufnummer(trans));
break;
case OPCODE_AT_K:
if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) {
@@ -1264,9 +1275,10 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
trans_new_state(trans, TRANS_AT);
trans->repeat = 0;
timer_stop(&trans->timer);
- if (cnetz->sender.callref) {
- call_in_release(cnetz->sender.callref, CAUSE_NORMAL);
+ if (trans->callref) {
+ call_in_release(trans->callref, CAUSE_NORMAL);
cnetz->sender.callref = 0;
+ trans->callref = 0;
}
break;
default:
@@ -1373,9 +1385,10 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm)
trans_new_state(trans, TRANS_AT);
trans->repeat = 0;
timer_stop(&trans->timer);
- if (cnetz->sender.callref) {
- call_in_release(cnetz->sender.callref, CAUSE_NORMAL);
+ if (trans->callref) {
+ call_in_release(trans->callref, CAUSE_NORMAL);
cnetz->sender.callref = 0;
+ trans->callref = 0;
}
break;
default:
diff --git a/src/cnetz/transaction.c b/src/cnetz/transaction.c
index 7c9ca03..378d5de 100644
--- a/src/cnetz/transaction.c
+++ b/src/cnetz/transaction.c
@@ -162,6 +162,25 @@ transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint
return NULL;
}
+transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref)
+{
+ transaction_t *trans = cnetz->trans_list;
+
+ /* just in case, this should not happen */
+ if (!callref)
+ return NULL;
+ while (trans) {
+ if (trans->callref == callref) {
+ 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) {
diff --git a/src/cnetz/transaction.h b/src/cnetz/transaction.h
index dd5c8d3..40ace98 100644
--- a/src/cnetz/transaction.h
+++ b/src/cnetz/transaction.h
@@ -27,6 +27,7 @@
typedef struct transaction {
struct transaction *next; /* pointer to next node in list */
cnetz_t *cnetz; /* pointer to cnetz instance */
+ int callref; /* callref for transaction */
uint8_t futln_nat; /* current station ID (3 values) */
uint8_t futln_fuvst;
uint16_t futln_rest;
@@ -48,6 +49,7 @@ 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);
+transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref);
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);