aboutsummaryrefslogtreecommitdiffstats
path: root/src/cnetz/cnetz.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cnetz/cnetz.c')
-rw-r--r--src/cnetz/cnetz.c647
1 files changed, 352 insertions, 295 deletions
diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c
index 08cb668..b3771d7 100644
--- a/src/cnetz/cnetz.c
+++ b/src/cnetz/cnetz.c
@@ -143,10 +143,12 @@
#include <math.h>
#include <inttypes.h>
#include "../libsample/sample.h"
-#include "../libdebug/debug.h"
+#include "../liblogging/logging.h"
#include "../libmobile/call.h"
#include "../libmobile/cause.h"
-#include "../libosmocc/message.h"
+#include "../libmobile/get_time.h"
+#include "../libmobile/console.h"
+#include <osmocom/cc/message.h>
#include "cnetz.h"
#include "database.h"
#include "sysinfo.h"
@@ -157,8 +159,16 @@
/* uncomment this to do echo debugging (-l) on Speech Channel */
//#define DEBUG_SPK
+#define FLOAT_TO_TIMEOUT(f) floor(f), ((f) - floor(f)) * 1000000
+
#define CUT_OFF_EMPHASIS_CNETZ 796.0 /* 200 uS time constant */
+/* OgK list of alternative channels, NOT including 131 */
+cnetz_t *ogk_list[16];
+int ogk_list_count = 0;
+int ogk_list_index = 0;
+
+
/* Convert channel number to frequency number of base station.
Set 'unterband' to 1 to get frequency of mobile station. */
double cnetz_kanal2freq(int kanal, int unterband)
@@ -178,6 +188,28 @@ double cnetz_kanal2freq(int kanal, int unterband)
return freq * 1e6;
}
+/* check if number is a valid station ID */
+const char *cnetz_number_valid(const char *number)
+{
+ /* assume that the number has valid length(s) and digits */
+
+ if (number[0] > '7')
+ return "Digit 1 (mobile country code) exceeds 7.";
+ if (number[7]) {
+ if ((number[1] - '0') == 0)
+ return "Digit 2 and 3 (mobile network code) of 8-digit number must be at least 10.";
+ if ((number[1] - '0') * 10 + (number[2] - '0') > 31)
+ return "Digit 2 and 3 (mobile network code) of 8-digit number exceed 31.";
+ if (atoi(number + 3) > 65535)
+ return "Digit 4 to 8 (mobile subscriber suffix) of 8-digit number exceed 65535.";
+ } else {
+ if (atoi(number + 2) > 65535)
+ return "Digit 3 to 7 (mobile subscriber suffix) of 7-digit number exceed 65535.";
+ }
+
+ return NULL;
+}
+
/* convert power level to P-bits by selecting next higher level */
static uint8_t cnetz_power2bits(int power)
{
@@ -198,7 +230,7 @@ static uint8_t cnetz_power2bits(int power)
}
}
-const char *cnetz_state_name(enum cnetz_state state)
+static const char *cnetz_state_name(enum cnetz_state state)
{
static char invalid[16];
@@ -235,13 +267,13 @@ static void cnetz_new_state(cnetz_t *cnetz, enum cnetz_state new_state)
{
if (cnetz->state == new_state)
return;
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "State change: %s -> %s\n", cnetz_state_name(cnetz->state), cnetz_state_name(new_state));
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "State change: %s -> %s\n", cnetz_state_name(cnetz->state), cnetz_state_name(new_state));
cnetz->state = new_state;
cnetz_display_status();
}
/* Convert ISDN cause to 'Ausloesegrund' of C-Netz mobile station */
-uint8_t cnetz_cause_isdn2cnetz(int cause)
+static uint8_t cnetz_cause_isdn2cnetz(int cause)
{
switch (cause) {
case CAUSE_NORMAL:
@@ -264,65 +296,71 @@ int cnetz_init(void)
}
/* Create transceiver instance and link to a list. */
-int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, double tx_gain, int challenge_valid, uint64_t challenge, int response_valid, uint64_t response, int warteschlange, int metering, double speech_deviation, int ms_power, int measure_speed, double clock_speed[2], int polarity, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback)
+int cnetz_create(const char *kanal_name, enum cnetz_chan_type chan_type, const char *device, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, double tx_gain, int challenge_valid, uint64_t challenge, int response_valid, uint64_t response, int warteschlange, int metering, double speech_deviation, int ms_power, int measure_speed, double clock_speed[2], int polarity, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback)
{
sender_t *sender;
cnetz_t *cnetz;
+ int kanal;
int rc;
- if ((atoi(kanal) & 1) && (atoi(kanal) < 3 || atoi(kanal) > 1147)) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Channel ('Kanal') number %s invalid. For odd channel numbers, use channel 3 ... 1147.\n", kanal);
+ kanal = atoi(kanal_name);
+ if ((kanal & 1) && (kanal < 3 || kanal > 1147)) {
+ LOGP(DCNETZ, LOGL_ERROR, "Channel ('Kanal') number %d invalid. For odd channel numbers, use channel 3 ... 1147.\n", kanal);
return -EINVAL;
}
- if ((atoi(kanal) & 1) && atoi(kanal) > 947) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "You defined an extended frequency channel %s, only newer phones support this!\n", kanal);
+ if ((kanal & 1) && kanal > 947) {
+ LOGP(DCNETZ, LOGL_NOTICE, "You defined an extended frequency channel %d, only newer phones support this!\n", kanal);
}
- if (!(atoi(kanal) & 1) && (atoi(kanal) < 4 || atoi(kanal) > 918)) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Channel ('Kanal') number %s invalid. For even channel numbers, use channel 4 ... 918.\n", kanal);
+ if (!(kanal & 1) && (kanal < 4 || kanal > 918)) {
+ LOGP(DCNETZ, LOGL_ERROR, "Channel ('Kanal') number %d invalid. For even channel numbers, use channel 4 ... 918.\n", kanal);
return -EINVAL;
}
- if (!(atoi(kanal) & 1) && atoi(kanal) > 758) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "You defined an extended frequency %s, only newer phones support this!\n", kanal);
- }
-
- /* OgK must be on channel 131 */
- if ((chan_type == CHAN_TYPE_OGK || chan_type == CHAN_TYPE_OGK_SPK) && atoi(kanal) != CNETZ_OGK_KANAL) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "You must use channel %d for calling channel ('Orga-Kanal') or for combined calling + traffic channel!\n", CNETZ_OGK_KANAL);
- return -EINVAL;
+ if (!(kanal & 1) && kanal > 758) {
+ LOGP(DCNETZ, LOGL_NOTICE, "You defined an extended frequency channel %d, only newer phones support this!\n", kanal);
}
/* SpK must be on channel other than 131 */
- if (chan_type == CHAN_TYPE_SPK && atoi(kanal) == CNETZ_OGK_KANAL) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "You must not use channel %d for traffic channel!\n", CNETZ_OGK_KANAL);
+ if (chan_type == CHAN_TYPE_SPK && kanal == CNETZ_STD_OGK_KANAL) {
+ LOGP(DCNETZ, LOGL_NOTICE, "You must not use channel %d for traffic channel!\n", CNETZ_STD_OGK_KANAL);
return -EINVAL;
}
/* warn if we combine SpK and OgK, this is not supported by standard */
if (chan_type == CHAN_TYPE_OGK_SPK) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "You selected channel %d ('Orga-Kanal') for combined calling + traffic channel. Some phones will reject this.\n", CNETZ_OGK_KANAL);
+ LOGP(DCNETZ, LOGL_NOTICE, "You selected channel %d ('Orga-Kanal') for combined control + traffic channel. Some phones will reject this.\n", kanal);
}
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *)sender;
- if (!!strcmp(sender->audiodev, audiodev)) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "To be able to sync multiple channels, all channels must be on the same sound device!\n");
+ if (!!strcmp(sender->device, device)) {
+ LOGP(DCNETZ, LOGL_NOTICE, "To be able to sync multiple channels, all channels must be on the same sound device!\n");
return -EINVAL;
}
}
cnetz = calloc(1, sizeof(cnetz_t));
if (!cnetz) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "No memory!\n");
+ LOGP(DCNETZ, LOGL_ERROR, "No memory!\n");
return -ENOMEM;
}
- PDEBUG(DCNETZ, DEBUG_DEBUG, "Creating 'C-Netz' instance for 'Kanal' = %s (sample rate %d).\n", kanal, samplerate);
+ LOGP(DCNETZ, LOGL_DEBUG, "Creating 'C-Netz' instance for 'Kanal' = %d (sample rate %d).\n", kanal, samplerate);
+
+ cnetz->kanal = kanal;
+ if ((chan_type == CHAN_TYPE_OGK || chan_type == CHAN_TYPE_OGK_SPK) && kanal != CNETZ_STD_OGK_KANAL) {
+ if (ogk_list_count == 16) {
+ LOGP(DCNETZ, LOGL_ERROR, "No more than 16 non-standard OGK are allowed!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ ogk_list[ogk_list_count++] = cnetz;
+ }
/* init general part of transceiver */
/* do not enable emphasis, since it is done by cnetz code, not by common sender code */
- rc = sender_create(&cnetz->sender, kanal, cnetz_kanal2freq(atoi(kanal), 0), cnetz_kanal2freq(atoi(kanal), 1), audiodev, use_sdr, samplerate, rx_gain, tx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE);
+ rc = sender_create(&cnetz->sender, kanal_name, cnetz_kanal2freq(kanal, 0), cnetz_kanal2freq(kanal, 1), device, use_sdr, samplerate, rx_gain, tx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE);
if (rc < 0) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to init transceiver process!\n");
goto error;
}
@@ -337,7 +375,7 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *
/* init audio processing */
rc = dsp_init_sender(cnetz, measure_speed, clock_speed, demod, speech_deviation);
if (rc < 0) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init signal processing!\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to init signal processing!\n");
goto error;
}
@@ -381,13 +419,13 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *
cnetz_go_idle(cnetz);
#ifdef DEBUG_SPK
- transaction_t *trans = create_transaction(cnetz, TRANS_DS, 2, 2, 22002, -1, -1);
+ transaction_t *trans = create_transaction(cnetz, TRANS_DS, 2, 2, 22002, -1, -1, NAN);
trans->mo_call = 1;
cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, (cnetz->sched_ts + 2) & 31);
#else
/* create transaction for speech channel loopback */
if (loopback && chan_type == CHAN_TYPE_SPK) {
- transaction_t *trans = create_transaction(cnetz, TRANS_VHQ_K, 2, 2, 22002, -1, -1);
+ transaction_t *trans = create_transaction(cnetz, TRANS_VHQ_K, 2, 2, 22002, -1, -1, NAN);
trans->mo_call = 1;
cnetz_set_dsp_mode(cnetz, DSP_MODE_SPK_K);
cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, (cnetz->sched_ts + 1) & 31);
@@ -397,21 +435,23 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *
#if 0
/* debug flushing transactions */
transaction_t *trans1, *trans2;
- trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1);
+ trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN);
destroy_transaction(trans1);
- trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1);
+ trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN);
destroy_transaction(trans1);
- trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1);
- trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1);
+ trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN);
+ trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1, NAN);
unlink_transaction(trans1);
link_transaction(trans1, cnetz);
cnetz_flush_other_transactions(cnetz, trans1);
- trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1);
+ trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1, NAN);
cnetz_flush_other_transactions(cnetz, trans2);
#endif
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Created 'Kanal' #%s of type '%s' = %s\n", kanal, chan_type_short_name(chan_type), chan_type_long_name(chan_type));
- PDEBUG(DNMT, DEBUG_NOTICE, " -> Using cell ID: Nat=%d FuVst=%d Rest=%d Name='%s'\n", si.fuz_nat, si.fuz_fuvst, si.fuz_rest, get_station_name(si.fuz_nat, si.fuz_fuvst, si.fuz_rest));
+ LOGP(DCNETZ, LOGL_NOTICE, "Created 'Kanal' #%d of type '%s' = %s\n", kanal, chan_type_short_name(chan_type), chan_type_long_name(chan_type));
+ const char *name, *long_name;
+ name = get_station_name(si.fuz_nat, si.fuz_fuvst, si.fuz_rest, &long_name);
+ LOGP(DCNETZ, LOGL_NOTICE, " -> Using cell ID: Nat=%d FuVst=%d Rest=%d Name='%s' Long Name='%s'\n", si.fuz_nat, si.fuz_fuvst, si.fuz_rest, name, long_name);
return 0;
@@ -427,11 +467,11 @@ void cnetz_destroy(sender_t *sender)
cnetz_t *cnetz = (cnetz_t *) sender;
transaction_t *trans;
- PDEBUG(DCNETZ, DEBUG_DEBUG, "Destroying 'C-Netz' instance for 'Kanal' = %s.\n", sender->kanal);
+ LOGP(DCNETZ, LOGL_DEBUG, "Destroying 'C-Netz' instance for 'Kanal' = %s.\n", sender->kanal);
while ((trans = search_transaction(cnetz, ~0))) {
const char *rufnummer = transaction2rufnummer(trans);
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Removing pending transaction for subscriber '%s'\n", rufnummer);
+ LOGP(DCNETZ, LOGL_NOTICE, "Removing pending transaction for subscriber '%s'\n", rufnummer);
destroy_transaction(trans);
}
@@ -449,9 +489,9 @@ static cnetz_t *search_free_spk(int extended)
cnetz = (cnetz_t *) sender;
/* ignore extended frequency, if not supported */
if (!extended) {
- if ((atoi(sender->kanal) & 1) && atoi(sender->kanal) > 947)
+ if ((cnetz->kanal & 1) && cnetz->kanal > 947)
continue;
- if (!(atoi(sender->kanal) & 1) && atoi(sender->kanal) > 758)
+ if (!(cnetz->kanal & 1) && cnetz->kanal > 758)
continue;
}
/* ignore busy channel */
@@ -468,7 +508,7 @@ static cnetz_t *search_free_spk(int extended)
return ogk_spk;
}
-static cnetz_t *search_ogk(void)
+static cnetz_t *search_ogk(int kanal)
{
sender_t *sender;
cnetz_t *cnetz;
@@ -478,6 +518,8 @@ static cnetz_t *search_ogk(void)
/* ignore busy channel */
if (cnetz->state != CNETZ_IDLE)
continue;
+ if (cnetz->kanal != kanal)
+ continue;
if (cnetz->chan_type == CHAN_TYPE_OGK)
return cnetz;
if (cnetz->chan_type == CHAN_TYPE_OGK_SPK)
@@ -490,40 +532,40 @@ static cnetz_t *search_ogk(void)
/* Abort connection, if any and send idle broadcast */
void cnetz_go_idle(cnetz_t *cnetz)
{
- cnetz_t *ogk;
transaction_t *trans;
if (cnetz->state == CNETZ_IDLE)
return;
if (cnetz->trans_list) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Releasing but still having transaction, please fix!\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Releasing but still having transaction, please fix!\n");
if (cnetz->trans_list->callref)
call_up_release(cnetz->trans_list->callref, CAUSE_NORMAL);
destroy_transaction(cnetz->trans_list);
}
- PDEBUG(DCNETZ, DEBUG_INFO, "Entering IDLE state on channel %s.\n", cnetz->sender.kanal);
+ LOGP(DCNETZ, LOGL_INFO, "Entering IDLE state on channel %s.\n", cnetz->sender.kanal);
cnetz_new_state(cnetz, CNETZ_IDLE);
+ cnetz->sched_lr_debugged = 0;
+ cnetz->sched_mlr_debugged = 0;
/* set scheduler to OgK or turn off SpK */
if (cnetz->dsp_mode == DSP_MODE_SPK_K || cnetz->dsp_mode == DSP_MODE_SPK_V) {
/* switch next frame after distributed signaling boundary (multiple of 8 slots) */
- cnetz_set_sched_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 8) & 24);
+ cnetz_set_sched_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 8) & 24);
} else {
/* switch next frame */
- cnetz_set_sched_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 1) & 31);
- cnetz_set_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF);
+ cnetz_set_sched_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 1) & 31);
+ cnetz_set_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF);
}
/* check for first phone in queue and trigger completion of call (becoming idle means that SpK is now available) */
- ogk = search_ogk();
- trans = search_transaction(ogk, TRANS_MT_QUEUE | TRANS_MO_QUEUE);
+ trans = search_transaction_queue();
if (trans) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Now channel available for queued subscriber '%s'.\n", transaction2rufnummer(trans));
+ LOGP(DCNETZ, LOGL_NOTICE, "Now channel is available for queued subscriber '%s'.\n", transaction2rufnummer(trans));
trans_new_state(trans, (trans->state == TRANS_MT_QUEUE) ? TRANS_MT_DELAY : TRANS_MO_DELAY);
- timer_stop(&trans->timer);
- timer_start(&trans->timer, 2.0);
+ osmo_timer_del(&trans->timer);
+ osmo_timer_schedule(&trans->timer, 3,0); /* Wait at least one frame cycles (2.4s) until timeout */
}
}
@@ -534,119 +576,67 @@ static void cnetz_release(transaction_t *trans, uint8_t cause)
trans->repeat = 0;
trans->release_cause = cause;
trans->cnetz->sched_dsp_mode_ts = -1;
- timer_stop(&trans->timer);
+ osmo_timer_del(&trans->timer);
}
-/* Receive audio from call instance. */
-void call_down_audio(int callref, sample_t *samples, int count)
-{
- sender_t *sender;
- cnetz_t *cnetz;
-
- for (sender = sender_head; sender; sender = sender->next) {
- cnetz = (cnetz_t *) sender;
- if (cnetz->trans_list && cnetz->trans_list->callref == callref)
- break;
- }
- if (!sender)
- return;
-
- if (cnetz->dsp_mode == DSP_MODE_SPK_V) {
- /* store as is, since we convert rate when processing FSK frames */
- jitter_save(&cnetz->sender.dejitter, samples, count);
- }
-}
-
-void call_down_clock(void) {}
-
int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char *dialing)
{
- sender_t *sender;
- cnetz_t *cnetz, *spk;
+ cnetz_t *ogk, *spk;
int rc;
int extended;
transaction_t *trans;
uint8_t futln_nat;
uint8_t futln_fuvst;
int futln_rest; /* use int for checking size > 65535 */
- int len;
- int i;
-
- /* 1. check if number is invalid, return INVALNUMBER */
- len = strlen(dialing);
- if (len >= 11 && !strncmp(dialing, "0161", 4)) {
- dialing += 4;
- len -= 4;
- }
- if (len < 7 || len > 8) {
-inval:
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to invalid number '%s', rejecting!\n", dialing);
- return -CAUSE_INVALNUMBER;
- }
- for (i = 0; i < len; i++) {
- if (dialing[i] < '0' || dialing[i] > '9')
- goto inval;
- }
+ int ogk_kanal;
+ /* 1. split number into elements */
futln_nat = dialing[0] - '0';
- if (len == 7)
- futln_fuvst = dialing[1] - '0';
- else {
+ if (dialing[7]) {
futln_fuvst = (dialing[1] - '0') * 10 + (dialing[2] - '0');
- if (futln_fuvst > 31) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Digit 2 and 3 '%02d' must not exceed '31', but they do!\n", futln_fuvst);
- goto inval;
- }
- }
- futln_rest = atoi(dialing + len - 5);
- if (futln_rest > 65535) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Last 5 digits '%05d' must not exceed '65535', but they do!\n", futln_rest);
- goto inval;
+ futln_rest = atoi(dialing + 3);
+ } else {
+ futln_fuvst = dialing[1] - '0';
+ futln_rest = atoi(dialing + 2);
}
/* 2. check if the subscriber is attached */
- rc = find_db(futln_nat, futln_fuvst, futln_rest, NULL, &extended);
+ rc = find_db(futln_nat, futln_fuvst, futln_rest, &ogk_kanal, NULL, &extended);
if (rc < 0) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n");
+ LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n");
return -CAUSE_OUTOFORDER;
}
/* 3. check if given number is already in a call, return BUSY */
- for (sender = sender_head; sender; sender = sender->next) {
- cnetz = (cnetz_t *) sender;
- /* search transaction for this number */
- trans = search_transaction_number(cnetz, futln_nat, futln_fuvst, futln_rest);
- if (trans)
- break;
- }
- if (sender) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to busy number, rejecting!\n");
+ trans = search_transaction_number_global(futln_nat, futln_fuvst, futln_rest);
+ if (trans) {
+ LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call to busy number, rejecting!\n");
return -CAUSE_BUSY;
}
/* 4. check if we have no OgK, return NOCHANNEL */
- cnetz = search_ogk();
- if (!cnetz) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n");
+ ogk = search_ogk(ogk_kanal);
+ if (!ogk) {
+ LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n");
return -CAUSE_NOCHANNEL;
}
/* 5. check if all senders are busy, return NOCHANNEL */
spk = search_free_spk(extended);
if (!spk) {
- if (!cnetz->warteschlange) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
+ if (!ogk->warteschlange) {
+ LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
return -CAUSE_NOCHANNEL;
} else
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, queuing call!\n");
+ LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call, but no free channel, queuing call!\n");
}
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
+ LOGP(DCNETZ, LOGL_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
/* 6. trying to page mobile station */
- trans = create_transaction(cnetz, (spk) ? TRANS_VAK : TRANS_WSK, dialing[0] - '0', dialing[1] - '0', atoi(dialing + 2), -1, -1);
+ trans = create_transaction(ogk, (spk) ? TRANS_VAK : TRANS_WSK, futln_nat, futln_fuvst, futln_rest, -1, -1, NAN);
if (!trans) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n");
return -CAUSE_TEMPFAIL;
}
trans->callref = callref;
@@ -655,8 +645,35 @@ inval:
return 0;
}
-void call_down_answer(int __attribute__((unused)) callref)
+void call_down_answer(int callref, struct timeval *tv_meter)
{
+ sender_t *sender;
+ cnetz_t *cnetz;
+ transaction_t *trans;
+
+ LOGP(DCNETZ, LOGL_INFO, "Call has been answered by network.\n");
+
+ for (sender = sender_head; sender; sender = sender->next) {
+ cnetz = (cnetz_t *) sender;
+ trans = search_transaction_callref(cnetz, callref);
+ if (trans)
+ break;
+ }
+ if (!sender) {
+ LOGP(DCNETZ, LOGL_NOTICE, "Incoming answer, but no callref!\n");
+ return;
+ }
+
+ /* At least tone second! */
+ if (tv_meter->tv_sec) {
+ LOGP(DCNETZ, LOGL_INFO, "Network starts metering pulses every %lu.%03lu seconds.\n", tv_meter->tv_sec, tv_meter->tv_usec / 1000);
+ trans->meter_start = get_time();
+ trans->metering_time = (double)tv_meter->tv_sec + (double)tv_meter->tv_usec / 1000000.0;
+ } else if (cnetz->metering) {
+ LOGP(DCNETZ, LOGL_INFO, "Command line options starts metering pulses every %d seconds.\n", cnetz->metering);
+ trans->meter_start = get_time();
+ trans->metering_time = (double)cnetz->metering;
+ }
}
/* Call control sends disconnect (with tones).
@@ -669,7 +686,7 @@ void call_down_disconnect(int callref, int cause)
cnetz_t *cnetz;
transaction_t *trans;
- PDEBUG(DCNETZ, DEBUG_INFO, "Call has been disconnected by network.\n");
+ LOGP(DCNETZ, LOGL_INFO, "Call has been disconnected by network.\n");
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
@@ -679,7 +696,7 @@ void call_down_disconnect(int callref, int cause)
break;
}
if (!sender) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing disconnect, but no callref!\n");
+ LOGP(DCNETZ, LOGL_NOTICE, "Outgoing disconnect, but no callref!\n");
call_up_release(callref, CAUSE_INVALCALLREF);
return;
}
@@ -688,15 +705,17 @@ void call_down_disconnect(int callref, int cause)
switch (cnetz->dsp_mode) {
case DSP_MODE_SPK_V:
+ /* stop metering */
+ trans->meter_end = get_time();
return;
case DSP_MODE_SPK_K:
- PDEBUG(DCNETZ, DEBUG_INFO, "Call control disconnects on speech channel, releasing towards mobile station.\n");
+ LOGP(DCNETZ, LOGL_INFO, "Call control disconnects on speech channel, releasing towards mobile station.\n");
cnetz_release(trans, cnetz_cause_isdn2cnetz(cause));
call_up_release(callref, cause);
trans->callref = 0;
break;
default:
- PDEBUG(DCNETZ, DEBUG_INFO, "Call control disconnects on organisation channel, removing transaction.\n");
+ LOGP(DCNETZ, LOGL_INFO, "Call control disconnects on organisation channel, removing transaction.\n");
call_up_release(callref, cause);
trans->callref = 0;
if (trans->state == TRANS_MT_QUEUE || trans->state == TRANS_MT_DELAY) {
@@ -716,7 +735,7 @@ void call_down_release(int callref, int cause)
cnetz_t *cnetz;
transaction_t *trans;
- PDEBUG(DCNETZ, DEBUG_INFO, "Call has been released by network, releasing call.\n");
+ LOGP(DCNETZ, LOGL_INFO, "Call has been released by network, releasing call.\n");
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
@@ -726,7 +745,7 @@ void call_down_release(int callref, int cause)
break;
}
if (!sender) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing release, but no callref!\n");
+ LOGP(DCNETZ, LOGL_NOTICE, "Outgoing release, but no callref!\n");
/* don't send release, because caller already released */
return;
}
@@ -736,11 +755,11 @@ void call_down_release(int callref, int cause)
switch (cnetz->dsp_mode) {
case DSP_MODE_SPK_K:
case DSP_MODE_SPK_V:
- PDEBUG(DCNETZ, DEBUG_INFO, "Call control releases on speech channel, releasing towards mobile station.\n");
+ LOGP(DCNETZ, LOGL_INFO, "Call control releases on speech channel, releasing towards mobile station.\n");
cnetz_release(trans, cnetz_cause_isdn2cnetz(cause));
break;
default:
- PDEBUG(DCNETZ, DEBUG_INFO, "Call control releases on organisation channel, removing transaction.\n");
+ LOGP(DCNETZ, LOGL_INFO, "Call control releases on organisation channel, removing transaction.\n");
if (trans->state == TRANS_MT_QUEUE) {
cnetz_release(trans, cnetz_cause_isdn2cnetz(cause));
} else {
@@ -750,19 +769,19 @@ void call_down_release(int callref, int cause)
}
}
-int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest)
+int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal)
{
cnetz_t *cnetz;
transaction_t *trans;
- cnetz = search_ogk();
+ cnetz = search_ogk(ogk_kanal);
if (!cnetz) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "'Meldeaufruf', but OgK is currently busy!\n");
+ LOGP(DCNETZ, LOGL_NOTICE, "'Meldeaufruf', but OgK is currently busy!\n");
return -CAUSE_NOCHANNEL;
}
- trans = create_transaction(cnetz, TRANS_MA, futln_nat, futln_fuvst, futln_rest, -1, -1);
+ trans = create_transaction(cnetz, TRANS_MA, futln_nat, futln_fuvst, futln_rest, -1, -1, NAN);
if (!trans) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n");
return -CAUSE_TEMPFAIL;
}
@@ -827,29 +846,20 @@ const char *chan_type_long_name(enum cnetz_chan_type chan_type)
}
/* Timeout handling */
-void transaction_timeout(struct timer *timer)
+void transaction_timeout(void *data)
{
- transaction_t *trans = (transaction_t *)timer->priv;
+ transaction_t *trans = data;
cnetz_t *cnetz = trans->cnetz;
switch (trans->state) {
- case TRANS_WAF:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after dialing request 'Wahlaufforderung'\n");
- if (trans->try == N) {
- trans_new_state(trans, TRANS_WBN);
- break;
- }
- trans->try++;
- trans_new_state(trans, TRANS_VWG);
- break;
case TRANS_MT_QUEUE:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Phone in queue, but still no channel available, releasing call!\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Phone in queue, but still no channel available, releasing call!\n");
call_up_release(trans->callref, CAUSE_NOCHANNEL);
trans->callref = 0;
cnetz_release(trans, CNETZ_CAUSE_GASSENBESETZT);
break;
case TRANS_MO_QUEUE:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Phone in queue, but still no channel available, releasing!\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Phone in queue, but still no channel available, releasing!\n");
cnetz_release(trans, CNETZ_CAUSE_GASSENBESETZT);
break;
case TRANS_MT_DELAY:
@@ -859,12 +869,12 @@ void transaction_timeout(struct timer *timer)
trans_new_state(trans, TRANS_VAG);
break;
case TRANS_BQ:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after channel allocation 'Belegung Quittung'\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after channel allocation 'Belegung Quittung'\n");
trans_new_state(trans, TRANS_AF);
trans->repeat = 0;
break;
case TRANS_ZFZ:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after sending random number 'Zufallszahl'\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after sending random number 'Zufallszahl'\n");
if (trans->callref) {
call_up_release(trans->callref, CAUSE_TEMPFAIL);
trans->callref = 0;
@@ -872,7 +882,7 @@ void transaction_timeout(struct timer *timer)
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
break;
case TRANS_AP:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after waiting for challenge response 'Autorisierungsparameter'\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after waiting for challenge response 'Autorisierungsparameter'\n");
if (trans->callref) {
call_up_release(trans->callref, CAUSE_TEMPFAIL);
trans->callref = 0;
@@ -882,9 +892,9 @@ void transaction_timeout(struct timer *timer)
case TRANS_VHQ_K:
case TRANS_VHQ_V:
if (cnetz->dsp_mode != DSP_MODE_SPK_V)
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response while holding call 'Quittung Verbindung halten'\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response while holding call 'Quittung Verbindung halten'\n");
else
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Lost signal from 'FuTln' (mobile station)\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Lost signal from 'FuTln' (mobile station)\n");
if (trans->callref) {
call_up_release(trans->callref, CAUSE_TEMPFAIL);
trans->callref = 0;
@@ -892,31 +902,25 @@ void transaction_timeout(struct timer *timer)
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
break;
case TRANS_DS:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after connect 'Durchschalten'\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after connect 'Durchschalten'\n");
call_up_release(trans->callref, CAUSE_TEMPFAIL);
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");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after ringing order 'Rufton anschalten'\n");
call_up_release(trans->callref, CAUSE_TEMPFAIL);
trans->callref = 0;
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
break;
case TRANS_AHQ:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after answer 'Abhebequittung'\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after answer 'Abhebequittung'\n");
call_up_release(trans->callref, CAUSE_TEMPFAIL);
trans->callref = 0;
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
break;
- case TRANS_MFT:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after keepalive order 'Meldeaufruf'\n");
- /* no response to availability check */
- trans->page_failed = 1;
- destroy_transaction(trans);
- break;
default:
- PDEBUG_CHAN(DCNETZ, DEBUG_ERROR, "Timeout unhandled in state %" PRIu64 "\n", trans->state);
+ LOGP_CHAN(DCNETZ, LOGL_ERROR, "Timeout unhandled in state %" PRIu64 "\n", trans->state);
}
}
@@ -948,13 +952,13 @@ void cnetz_sync_frame(cnetz_t *cnetz, double sync, int block)
}
/* if more than +- one bit out of sync */
if (offset < -0.5 || offset > 0.5) {
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Frame sync offset = %.2f, correcting!\n", offset);
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Frame sync offset = %.2f, correcting!\n", offset);
fsk_correct_sync(&cnetz->fsk_demod, offset);
return;
}
/* resync by some fraction of received sync error */
- PDEBUG_CHAN(DCNETZ, DEBUG_DEBUG, "Frame sync offset = %.2f, correcting.\n", offset);
+ LOGP_CHAN(DCNETZ, LOGL_DEBUG, "Frame sync offset = %.2f, correcting.\n", offset);
fsk_correct_sync(&cnetz->fsk_demod, offset / 2.0);
}
@@ -984,6 +988,7 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz)
telegramm.fuz_fuvst_nr = si.fuz_fuvst;
telegramm.fuz_rest_nr = si.fuz_rest;
telegramm.kennung_fufst = si.kennung_fufst;
+ telegramm.bahn_bs = si.bahn_bs;
telegramm.nachbarschafts_prioritaets_bit = si.nachbar_prio;
telegramm.bewertung_nach_pegel_und_entfernung = si.bewertung;
telegramm.entfernungsangabe_der_fufst = si.entfernung;
@@ -992,7 +997,7 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz)
telegramm.grenzwert_fuer_umschalten = si.grenz_umschalten;
telegramm.grenze_fuer_ausloesen = si.grenz_ausloesen;
- trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK | TRANS_ATQ | TRANS_VA | TRANS_WSK);
+ trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK | TRANS_ATQ | TRANS_ATQ_IDLE | TRANS_VA | TRANS_WSK);
if (trans) {
telegramm.futln_nationalitaet = trans->futln_nat;
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
@@ -1000,18 +1005,18 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz)
telegramm.ausloesegrund = trans->release_cause;
switch (trans->state) {
case TRANS_EM:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Einbuchquittung' to Attachment request.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledgment 'Einbuchquittung' to Attachment request.\n");
telegramm.opcode = OPCODE_EBQ_R;
destroy_transaction(trans);
break;
case TRANS_UM:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Umbuchquittung' to Roaming requuest.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledgment 'Umbuchquittung' to Roaming requuest.\n");
telegramm.opcode = OPCODE_UBQ_R;
destroy_transaction(trans);
break;
case TRANS_WBN:
wbn:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending call reject 'Wahlbestaetigung negativ'.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending call reject 'Wahlbestaetigung negativ'.\n");
telegramm.opcode = OPCODE_WBN_R;
destroy_transaction(trans);
cnetz_go_idle(cnetz);
@@ -1020,17 +1025,17 @@ wbn:
spk = search_free_spk(trans->extended);
/* Accept call if channel available, otherwise reject or queue call */
if (spk) {
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending call accept 'Wahlbestaetigung positiv'.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending call accept 'Wahlbestaetigung positiv'.\n");
telegramm.opcode = OPCODE_WBP_R;
trans_new_state(trans, TRANS_VAG);
} else if (cnetz->warteschlange) {
/* queue call if no channel is available, but queue allowed */
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "No free channel, sending call accept in queue 'Wahlbestaetigung positiv in Warteschlage'.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "No free channel, sending call accept in queue 'Wahlbestaetigung positiv in Warteschlage'.\n");
telegramm.opcode = OPCODE_WWBP_R;
trans_new_state(trans, TRANS_MO_QUEUE);
- timer_start(&trans->timer, T_VAG2); /* Maximum time to hold queue */
+ osmo_timer_schedule(&trans->timer, T_VAG2); /* Maximum time to hold queue */
} else {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "No free channel anymore, rejecting call!\n");
+ LOGP(DCNETZ, LOGL_NOTICE, "No free channel anymore, rejecting call!\n");
trans_new_state(trans, TRANS_WBN);
goto wbn;
}
@@ -1039,32 +1044,32 @@ wbn:
case TRANS_VAK:
vak:
if (trans->state == TRANS_VAG) {
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending channel assignment 'Verbindungsaufbau gehend'.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending channel assignment 'Verbindungsaufbau gehend'.\n");
telegramm.opcode = OPCODE_VAG_R;
} else {
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending channel assignment 'Verbindungsaufbau kommend'.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending channel assignment 'Verbindungsaufbau kommend'.\n");
telegramm.opcode = OPCODE_VAK_R;
}
trans_new_state(trans, TRANS_BQ);
trans->repeat = 0;
- timer_start(&trans->timer, 0.150 + 0.0375 * F_BQ); /* two slots + F_BQ frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.150 + 0.0375 * F_BQ)); /* two slots + F_BQ frames */
/* select channel */
spk = search_free_spk(trans->extended);
if (!spk) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "No free channel anymore, rejecting call!\n");
+ LOGP(DCNETZ, LOGL_NOTICE, "No free channel anymore, rejecting call!\n");
destroy_transaction(trans);
cnetz_go_idle(cnetz);
break;
}
if (spk == cnetz) {
- PDEBUG(DCNETZ, DEBUG_INFO, "Staying on combined calling + traffic channel %s\n", spk->sender.kanal);
+ LOGP(DCNETZ, LOGL_INFO, "Staying on combined control + traffic channel %s\n", spk->sender.kanal);
} else {
- PDEBUG(DCNETZ, DEBUG_INFO, "Assigning phone to traffic channel %s\n", spk->sender.kanal);
+ LOGP(DCNETZ, LOGL_INFO, "Assigning phone to traffic channel %s\n", spk->sender.kanal);
/* sync RX time to current OgK time */
fsk_copy_sync(&spk->fsk_demod, &cnetz->fsk_demod);
}
/* set channel */
- telegramm.frequenz_nr = atoi(spk->sender.kanal);
+ telegramm.frequenz_nr = spk->kanal;
/* change state to busy */
cnetz_new_state(spk, CNETZ_BUSY);
/* schedule switching two slots ahead */
@@ -1076,12 +1081,13 @@ vak:
cnetz_flush_other_transactions(spk, trans);
break;
case TRANS_ATQ:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Quittung fuer Ausloesen des FuTelG im OgK-Betrieb' to release request.\n");
+ case TRANS_ATQ_IDLE:
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledgment 'Quittung fuer Ausloesen des FuTelG im OgK-Betrieb' to release request.\n");
telegramm.opcode = OPCODE_ATQ_R;
destroy_transaction(trans);
break;
case TRANS_VA:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Vorzeitiges Ausloesen' to queued mobile station\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Vorzeitiges Ausloesen' to queued mobile station\n");
telegramm.opcode = OPCODE_VA_R;
destroy_transaction(trans);
break;
@@ -1092,10 +1098,10 @@ vak:
trans_new_state(trans, TRANS_VAK);
goto vak;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "No free channel, sending incoming call in queue 'Warteschglange kommend'.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "No free channel, sending incoming call in queue 'Warteschglange kommend'.\n");
telegramm.opcode = OPCODE_WSK_R;
trans_new_state(trans, TRANS_MT_QUEUE);
- timer_start(&trans->timer, T_VAK); /* Maximum time to hold queue */
+ osmo_timer_schedule(&trans->timer, T_VAK); /* Maximum time to hold queue */
call_up_alerting(trans->callref);
default:
; /* LR */
@@ -1114,33 +1120,54 @@ const telegramm_t *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz)
memset(&telegramm, 0, sizeof(telegramm));
telegramm.opcode = OPCODE_MLR_M;
telegramm.max_sendeleistung = cnetz_power2bits(cnetz->ms_power);
- telegramm.ogk_verkehrsanteil = 0; /* must be 0 or phone might not respond to messages in different slot */
+ telegramm.ogk_verkehrsanteil = 0; /* must be 0 or some phone might not respond to messages in different slots */
telegramm.teilnehmergruppensperre = si.teilnehmergruppensperre;
telegramm.anzahl_gesperrter_teilnehmergruppen = si.anzahl_gesperrter_teilnehmergruppen;
- telegramm.ogk_vorschlag = CNETZ_OGK_KANAL;
+ if (ogk_list_count) {
+ /* if we have alternative OGKs, we cycle through the list and indicate their channels */
+ telegramm.ogk_vorschlag = ogk_list[ogk_list_index]->kanal;
+ if (++ogk_list_index == ogk_list_count)
+ ogk_list_index = 0;
+ } else
+ telegramm.ogk_vorschlag = CNETZ_STD_OGK_KANAL;
telegramm.fuz_rest_nr = si.fuz_rest;
- trans = search_transaction(cnetz, TRANS_VWG | TRANS_MA);
+next_candidate:
+ trans = search_transaction(cnetz, TRANS_VWG | TRANS_WAF | TRANS_MA | TRANS_MFT);
if (trans) {
switch (trans->state) {
+ case TRANS_WAF:
+ /* no response to dial request (try again or drop connection) */
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after dialing request 'Wahlaufforderung'\n");
+ if (trans->try == N) {
+ trans_new_state(trans, TRANS_WBN);
+ goto next_candidate;
+ }
+ trans->try++;
+ trans_new_state(trans, TRANS_VWG);
+ /* FALLTHRU */
case TRANS_VWG:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Wahlaufforderung' to outging call\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledgment 'Wahlaufforderung' to outging call\n");
telegramm.opcode = OPCODE_WAF_M;
telegramm.futln_nationalitaet = trans->futln_nat;
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
telegramm.futln_rest_nr = trans->futln_rest;
trans_new_state(trans, TRANS_WAF);
- timer_start(&trans->timer, 1.0); /* Wait two slot cycles until resending */
break;
case TRANS_MA:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending keepalive request 'Meldeaufruf'\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending keepalive request 'Meldeaufruf'\n");
telegramm.opcode = OPCODE_MA_M;
telegramm.futln_nationalitaet = trans->futln_nat;
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
telegramm.futln_rest_nr = trans->futln_rest;
trans_new_state(trans, TRANS_MFT);
- timer_start(&trans->timer, 1.0); /* Wait two slot cycles until timeout */
break;
+ case TRANS_MFT:
+ /* no response to availability check */
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after keepalive order 'Meldeaufruf'\n");
+ trans->page_failed = 1;
+ destroy_transaction(trans);
+ goto next_candidate;
default:
; /* MLR */
}
@@ -1162,20 +1189,22 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
break;
rufnummer = telegramm2rufnummer(telegramm);
if (si.authentifikationsbit && telegramm->chipkarten_futelg_bit)
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Attachment 'Einbuchen' message from Subscriber '%s' with chip card's ID %d (vendor id %d, hardware version %d, software version %d)\n", rufnummer, telegramm->kartenkennung, telegramm->herstellerkennung, telegramm->hardware_des_futelg, telegramm->software_des_futelg);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Attachment 'Einbuchen' message from Subscriber '%s' with chip card's ID %d (vendor id %d, hardware version %d, software version %d)\n", rufnummer, telegramm->kartenkennung, telegramm->herstellerkennung, telegramm->hardware_des_futelg, telegramm->software_des_futelg);
else
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Attachment 'Einbuchen' message from Subscriber '%s' with %s card's security code %d\n", rufnummer, (telegramm->chipkarten_futelg_bit) ? "chip":"magnet", telegramm->sicherungs_code);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Attachment 'Einbuchen' message from Subscriber '%s' with %s card's security code %d\n", rufnummer, (telegramm->chipkarten_futelg_bit) ? "chip":"magnet", telegramm->sicherungs_code);
if (telegramm->erweitertes_frequenzbandbit)
- PDEBUG(DCNETZ, DEBUG_INFO, " -> Phone supports extended frequency band\n");
+ LOGP(DCNETZ, LOGL_INFO, " -> Phone supports extended frequency band\n");
if (cnetz->state != CNETZ_IDLE) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Attachment from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
+ LOGP(DCNETZ, LOGL_NOTICE, "Ignoring Attachment from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
break;
}
- trans = create_transaction(cnetz, TRANS_EM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit);
+ console_inscription(rufnummer);
+ trans = create_transaction(cnetz, TRANS_EM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db);
if (!trans) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n");
break;
}
+ cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
valid_frame = 1;
break;
case OPCODE_UM_R:
@@ -1183,20 +1212,22 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
break;
rufnummer = telegramm2rufnummer(telegramm);
if (si.authentifikationsbit && telegramm->chipkarten_futelg_bit)
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Roaming 'Umbuchen' message from Subscriber '%s' with chip card's ID %d (vendor id %d, hardware version %d, software version %d)\n", rufnummer, telegramm->kartenkennung, telegramm->herstellerkennung, telegramm->hardware_des_futelg, telegramm->software_des_futelg);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Roaming 'Umbuchen' message from Subscriber '%s' with chip card's ID %d (vendor id %d, hardware version %d, software version %d)\n", rufnummer, telegramm->kartenkennung, telegramm->herstellerkennung, telegramm->hardware_des_futelg, telegramm->software_des_futelg);
else
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Roaming 'Umbuchen' message from Subscriber '%s' with %s card's security code %d\n", rufnummer, (telegramm->chipkarten_futelg_bit) ? "chip":"magnet", telegramm->sicherungs_code);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Roaming 'Umbuchen' message from Subscriber '%s' with %s card's security code %d\n", rufnummer, (telegramm->chipkarten_futelg_bit) ? "chip":"magnet", telegramm->sicherungs_code);
if (telegramm->erweitertes_frequenzbandbit)
- PDEBUG(DCNETZ, DEBUG_INFO, " -> Phone supports extended frequency band\n");
+ LOGP(DCNETZ, LOGL_INFO, " -> Phone supports extended frequency band\n");
if (cnetz->state != CNETZ_IDLE) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Roaming from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
+ LOGP(DCNETZ, LOGL_NOTICE, "Ignoring Roaming from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
break;
}
- trans = create_transaction(cnetz, TRANS_UM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit);
+ console_inscription(rufnummer);
+ trans = create_transaction(cnetz, TRANS_UM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db);
if (!trans) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n");
break;
}
+ cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
valid_frame = 1;
break;
case OPCODE_UWG_R:
@@ -1204,39 +1235,43 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
if (!match_fuz(telegramm))
break;
rufnummer = telegramm2rufnummer(telegramm);
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Roaming request 'Umbuchantrag' message from Subscriber '%s' on queue\n", rufnummer);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Roaming request 'Umbuchantrag' message from Subscriber '%s' on queue\n", rufnummer);
break;
case OPCODE_VWG_R:
case OPCODE_SRG_R:
+ case OPCODE_NUG_R:
if (!match_fuz(telegramm))
break;
rufnummer = telegramm2rufnummer(telegramm);
if (opcode == OPCODE_VWG_R)
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing Call 'Verbindungswunsch gehend' message from Subscriber '%s'\n", rufnummer);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received outgoing Call 'Verbindungswunsch gehend' message from Subscriber '%s'\n", rufnummer);
+ else if (opcode == OPCODE_SRG_R)
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received outgoing emergency Call 'Sonderruf gehend' message from Subscriber '%s'\n", rufnummer);
else
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing emergency Call 'Sonderruf gehend' message from Subscriber '%s'\n", rufnummer);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received outgoing Call 'Verbindungswunsch gehend bei Nachbarschaftsunterstuetzung' message from Subscriber '%s'\n", rufnummer);
if (cnetz->state != CNETZ_IDLE) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Call from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
+ LOGP(DCNETZ, LOGL_NOTICE, "Ignoring Call from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
break;
}
- trans = create_transaction(cnetz, TRANS_VWG, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, telegramm->erweitertes_frequenzbandbit);
+ trans = create_transaction(cnetz, TRANS_VWG, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db);
if (!trans) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n");
break;
}
+ cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
trans->try = 1;
valid_frame = 1;
break;
case OPCODE_WUE_M:
trans = search_transaction(cnetz, TRANS_WAF | TRANS_WBP | TRANS_VAG | TRANS_MO_QUEUE);
if (!trans) {
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received dialing digits 'Wahluebertragung' message without transaction, ignoring!\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received dialing digits 'Wahluebertragung' message without transaction (on this OgK), ignoring!\n");
break;
}
rufnummer = transaction2rufnummer(trans);
strncpy(trans->dialing, telegramm->wahlziffern, sizeof(trans->dialing) - 1);
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received dialing digits 'Wahluebertragung' message from Subscriber '%s' to Number '%s'\n", rufnummer, trans->dialing);
- timer_stop(&trans->timer);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received dialing digits 'Wahluebertragung' message from Subscriber '%s' to Number '%s'\n", rufnummer, trans->dialing);
+ osmo_timer_del(&trans->timer);
trans_new_state(trans, TRANS_WBP);
trans->try = 1; /* try */
valid_frame = 1;
@@ -1245,18 +1280,31 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
if (!match_fuz(telegramm))
break;
rufnummer = telegramm2rufnummer(telegramm);
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message from Subscriber '%s'\n", rufnummer);
- trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message from Subscriber '%s'\n", rufnummer);
+ trans = search_transaction_number_global(telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
if (!trans) {
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "There is no transaction, so we assume that the phone did not receive previous release.\n");
/* create transaction, in case the phone repeats the release after we have acked it */
- trans = create_transaction(cnetz, TRANS_ATQ, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1);
+ trans = create_transaction(cnetz, TRANS_ATQ_IDLE, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1, cnetz->rf_level_db);
if (!trans) {
- PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n");
break;
}
+ cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
} else {
- timer_stop(&trans->timer);
- trans_new_state(trans, TRANS_ATQ);
+ if (cnetz == trans->cnetz) {
+ osmo_timer_del(&trans->timer);
+ trans_new_state(trans, TRANS_ATQ);
+ } else
+ if (trans->state == TRANS_ATQ_IDLE) {
+ trans = create_transaction(cnetz, TRANS_ATQ_IDLE, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1, cnetz->rf_level_db);
+ if (!trans) {
+ LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n");
+ break;
+ }
+ cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
+ } else
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message without transaction (on this OgK), ignoring!\n");
}
valid_frame = 1;
break;
@@ -1265,16 +1313,16 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
break;
trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
if (!trans) {
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received acknowledge 'Meldung Funktelefonteilnehmer' message without transaction, ignoring!\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received acknowledge 'Meldung Funktelefonteilnehmer' message without transaction (on this OgK), ignoring!\n");
break;
}
rufnummer = transaction2rufnummer(trans);
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received acknowledge 'Meldung Funktelefonteilnehmer' message from Subscriber '%s'\n", rufnummer);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received acknowledge 'Meldung Funktelefonteilnehmer' message from Subscriber '%s'\n", rufnummer);
destroy_transaction(trans);
valid_frame = 1;
break;
default:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode));
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode));
}
if (cnetz->sender.loopback) {
@@ -1295,7 +1343,9 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz)
{
static telegramm_t telegramm;
transaction_t *trans = cnetz->trans_list;
+ int ogk_kanal;
cnetz_t *ogk;
+ int rc;
if (!trans)
return NULL;
@@ -1311,95 +1361,96 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz)
telegramm.futln_nationalitaet = trans->futln_nat;
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
telegramm.futln_rest_nr = trans->futln_rest;
- telegramm.frequenz_nr = atoi(cnetz->sender.kanal);
+ telegramm.frequenz_nr = cnetz->kanal;
telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit;
telegramm.zufallszahl = cnetz->challenge;
+ telegramm.bahn_bs = si.bahn_bs;
switch (trans->state) {
case TRANS_BQ:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Belegungsquittung' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Belegungsquittung' on traffic channel\n");
telegramm.opcode = OPCODE_BQ_K;
- if (++trans->repeat >= 8 && !timer_running(&trans->timer)) {
+ if (++trans->repeat >= 8 && !osmo_timer_pending(&trans->timer)) {
if (cnetz->challenge_valid) {
if (si.authentifikationsbit == 0) {
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Cannot authenticate, because base station does not support it. (Authentication disabled in sysinfo.)\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Cannot authenticate, because base station does not support it. (Authentication disabled in sysinfo.)\n");
goto no_auth;
}
if (trans->futelg_bit == 0) {
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Cannot authenticate, because mobile station does not support it. (Mobile station has magnetic card.)\n");
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Cannot authenticate, because mobile station does not support it. (Mobile station has magnetic card.)\n");
goto no_auth;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Perform authentication with subscriber's card, use challenge: 0x%016" PRIx64 "\n", telegramm.zufallszahl);
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Perform authentication with subscriber's card, use challenge: 0x%016" PRIx64 "\n", telegramm.zufallszahl);
trans_new_state(trans, TRANS_ZFZ);
- timer_start(&trans->timer, 0.0375 * F_ZFZ); /* F_ZFZ frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_ZFZ)); /* F_ZFZ frames */
} else {
no_auth:
trans_new_state(trans, TRANS_VHQ_K);
- timer_start(&trans->timer, 0.0375 * F_VHQK); /* F_VHQK frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_VHQK)); /* F_VHQK frames */
}
trans->repeat = 0;
}
break;
case TRANS_ZFZ:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Zufallszahl' on traffic channel (0x%016" PRIx64 ").\n", telegramm.zufallszahl);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Zufallszahl' on traffic channel (0x%016" PRIx64 ").\n", telegramm.zufallszahl);
telegramm.opcode = OPCODE_ZFZ_K;
break;
case TRANS_AP:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Quittung Verbindung halten' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Quittung Verbindung halten' on traffic channel\n");
telegramm.opcode = OPCODE_VHQ_K;
break;
case TRANS_VHQ_K:
if (!cnetz->sender.loopback)
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Quittung Verbindung halten' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Quittung Verbindung halten' on traffic channel\n");
telegramm.opcode = OPCODE_VHQ_K;
/* continue until next sub frame, so we send DS from first block of next sub frame. */
- if (!cnetz->sender.loopback && (cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !timer_running(&trans->timer)) {
+ if (!cnetz->sender.loopback && (cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !osmo_timer_pending(&trans->timer)) {
/* next sub frame */
if (trans->mo_call) {
trans->callref = call_up_setup(transaction2rufnummer(trans), trans->dialing, OSMO_CC_NETWORK_CNETZ_NONE, "");
trans_new_state(trans, TRANS_DS);
trans->repeat = 0;
- timer_start(&trans->timer, 0.0375 * F_DS); /* F_DS frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_DS)); /* F_DS frames */
}
if (trans->mt_call) {
trans_new_state(trans, TRANS_RTA);
- timer_start(&trans->timer, 0.0375 * F_RTA); /* F_RTA frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_RTA)); /* F_RTA frames */
trans->repeat = 0;
call_up_alerting(trans->callref);
}
}
break;
case TRANS_DS:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Durchschalten' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Durchschalten' on traffic channel\n");
telegramm.opcode = OPCODE_DSB_K;
/* send exactly a sub frame (8 time slots) */
- if ((cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !timer_running(&trans->timer)) {
+ if ((cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !osmo_timer_pending(&trans->timer)) {
/* next sub frame */
trans_new_state(trans, TRANS_VHQ_V);
trans->repeat = 0;
cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_V, (cnetz->sched_ts + 1) & 31);
#ifndef DEBUG_SPK
- timer_start(&trans->timer, 0.075 + 0.6 * F_VHQ); /* one slot + F_VHQ frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.075 + 0.6 * F_VHQ)); /* one slot + F_VHQ frames */
#endif
}
break;
case TRANS_RTA:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Rufton anschalten' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Rufton anschalten' on traffic channel\n");
telegramm.opcode = OPCODE_RTA_K;
break;
case TRANS_AHQ:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Abhebe Quittung' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Abhebe Quittung' on traffic channel\n");
telegramm.opcode = OPCODE_AHQ_K;
if ((cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m) {
/* next sub frame */
trans_new_state(trans, TRANS_VHQ_V);
trans->repeat = 0;
cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_V, (cnetz->sched_ts + 1) & 31);
- timer_start(&trans->timer, 0.075 + 0.6 * F_VHQ); /* one slot + F_VHQ frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.075 + 0.6 * F_VHQ)); /* one slot + F_VHQ frames */
}
break;
case TRANS_AF:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n");
telegramm.opcode = OPCODE_AF_K;
if (++trans->repeat < N_AFKT)
break;
@@ -1410,7 +1461,7 @@ no_auth:
break;
}
if (trans->try == N) {
- PDEBUG(DCNETZ, DEBUG_INFO, "Maximum retries, removing transaction\n");
+ LOGP(DCNETZ, LOGL_INFO, "Maximum retries, removing transaction\n");
/* no response to incomming call */
trans->page_failed = 1;
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
@@ -1426,9 +1477,15 @@ no_auth:
/* idle channel */
cnetz_go_idle(cnetz);
/* alloc ogk again */
- ogk = search_ogk();
+ rc = find_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, &ogk_kanal, NULL, NULL);
+ if (rc < 0) {
+ LOGP(DCNETZ, LOGL_NOTICE, "Cannot find subscriber in database anymore, releasing!\n");
+ goto no_ogk;
+ }
+ ogk = search_ogk(ogk_kanal);
if (!ogk) {
- PDEBUG(DCNETZ, DEBUG_NOTICE, "Cannot retry, because currently no OgK available (busy)\n");
+ LOGP(DCNETZ, LOGL_NOTICE, "Cannot retry, because currently no OgK available (busy)\n");
+no_ogk:
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
if (trans->callref)
call_up_release(trans->callref, CAUSE_NOCHANNEL);
@@ -1436,7 +1493,7 @@ no_auth:
destroy_transaction(trans);
break;
}
- PDEBUG(DCNETZ, DEBUG_INFO, "Retry to assign channel.\n");
+ LOGP(DCNETZ, LOGL_INFO, "Retry to assign channel.\n");
/* attach call to OgK */
link_transaction(trans, ogk);
/* change state */
@@ -1447,7 +1504,7 @@ no_auth:
trans->try++;
break;
case TRANS_AT:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Auslosen durch FuFst' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Auslosen durch FuFst' on traffic channel\n");
telegramm.opcode = OPCODE_AF_K;
if (++trans->repeat == 1) {
destroy_transaction(trans);
@@ -1477,11 +1534,11 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) {
break;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received allocation 'Belegung' message.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received allocation 'Belegung' message.\n");
valid_frame = 1;
if (trans->state != TRANS_BQ)
break;
- timer_stop(&trans->timer);
+ osmo_timer_del(&trans->timer);
trans->try = 0;
break;
case OPCODE_DSQ_K:
@@ -1491,35 +1548,35 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) {
break;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received assignment confirm 'Durchschaltung Quittung' message.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received assignment confirm 'Durchschaltung Quittung' message.\n");
valid_frame = 1;
if (trans->state != TRANS_DS)
break;
cnetz->scrambler = telegramm->betriebs_art;
cnetz->scrambler_switch = 0;
- timer_stop(&trans->timer);
+ osmo_timer_del(&trans->timer);
break;
case OPCODE_ZFZQ_K:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received random number acknowledge 'Zufallszahlquittung' message.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received random number acknowledge 'Zufallszahlquittung' message.\n");
valid_frame = 1;
if (trans->state != TRANS_ZFZ)
break;
if (cnetz->challenge != telegramm->zufallszahl) {
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received random number acknowledge (0x%016" PRIx64 ") does not match the transmitted one (0x%016" PRIx64 "), ignoring!\n", telegramm->zufallszahl, cnetz->challenge);
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received random number acknowledge (0x%016" PRIx64 ") does not match the transmitted one (0x%016" PRIx64 "), ignoring!\n", telegramm->zufallszahl, cnetz->challenge);
break;
}
- timer_stop(&trans->timer);
+ osmo_timer_del(&trans->timer);
trans_new_state(trans, TRANS_AP);
- timer_start(&trans->timer, T_AP); /* 750 milliseconds */
+ osmo_timer_schedule(&trans->timer, T_AP); /* 750 milliseconds */
break;
case OPCODE_AP_K:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received challenge response 'Autorisierungsparameter' message (0x%016" PRIx64 ").\n", telegramm->authorisierungsparameter);
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received challenge response 'Autorisierungsparameter' message (0x%016" PRIx64 ").\n", telegramm->authorisierungsparameter);
valid_frame = 1;
if (trans->state != TRANS_AP)
break;
/* if authentication response from card does not match */
if (cnetz->response_valid && telegramm->authorisierungsparameter != cnetz->response) {
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received challenge response (0x%016" PRIx64 ") does not match the expected one (0x%016" PRIx64 "), releasing!\n", telegramm->authorisierungsparameter, cnetz->response);
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received challenge response (0x%016" PRIx64 ") does not match the expected one (0x%016" PRIx64 "), releasing!\n", telegramm->authorisierungsparameter, cnetz->response);
if (trans->callref) {
call_up_release(trans->callref, CAUSE_TEMPFAIL); /* jolly guesses that */
trans->callref = 0;
@@ -1527,10 +1584,10 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
cnetz_release(trans, CNETZ_CAUSE_GASSENBESETZT); /* when authentication is not valid */
break;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Completed authentication with subscriber's card, challenge response: 0x%016" PRIx64 "\n", telegramm->authorisierungsparameter);
- timer_stop(&trans->timer);
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Completed authentication with subscriber's card, challenge response: 0x%016" PRIx64 "\n", telegramm->authorisierungsparameter);
+ osmo_timer_del(&trans->timer);
trans_new_state(trans, TRANS_VHQ_K);
- timer_start(&trans->timer, 0.0375 * F_VHQK); /* F_VHQK frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_VHQK)); /* F_VHQK frames */
break;
case OPCODE_VH_K:
if (!match_fuz(telegramm)) {
@@ -1539,11 +1596,11 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) {
break;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received connection hold 'Verbindung halten' message.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received connection hold 'Verbindung halten' message.\n");
valid_frame = 1;
if (trans->state != TRANS_VHQ_K)
break;
- timer_stop(&trans->timer);
+ osmo_timer_del(&trans->timer);
break;
case OPCODE_RTAQ_K:
if (!match_fuz(telegramm)) {
@@ -1553,10 +1610,10 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
break;
}
valid_frame = 1;
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received ringback 'Rufton anschalten Quittung' message.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received ringback 'Rufton anschalten Quittung' message.\n");
if (trans->state != TRANS_RTA)
break;
- timer_start(&trans->timer, 0.0375 * F_RTA); /* F_RTA frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_RTA)); /* F_RTA frames */
break;
case OPCODE_AH_K:
if (!match_fuz(telegramm)) {
@@ -1565,7 +1622,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) {
break;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received answer frame 'Abheben' message.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received answer frame 'Abheben' message.\n");
valid_frame = 1;
/* if already received this frame, or if we are already on VHQ or if we are releasing */
if (trans->state == TRANS_AHQ || trans->state == TRANS_VHQ_K || trans->state == TRANS_VHQ_V || trans->state == TRANS_AF)
@@ -1574,7 +1631,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
cnetz->scrambler_switch = 0;
trans_new_state(trans, TRANS_AHQ);
trans->repeat = 0;
- timer_stop(&trans->timer);
+ osmo_timer_del(&trans->timer);
call_up_answer(trans->callref, transaction2rufnummer(trans));
break;
case OPCODE_AT_K:
@@ -1584,21 +1641,21 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm)
if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) {
break;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received release frame 'Ausloesen durch FuTln' message.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received release frame 'Ausloesen durch FuTln' message.\n");
valid_frame = 1;
/* if already received this frame, if we are releasing */
if (trans->state == TRANS_AT || trans->state == TRANS_AF)
break;
trans_new_state(trans, TRANS_AT);
trans->repeat = 0;
- timer_stop(&trans->timer);
+ osmo_timer_del(&trans->timer);
if (trans->callref) {
call_up_release(trans->callref, CAUSE_NORMAL);
trans->callref = 0;
}
break;
default:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode));
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode));
}
if (valid_frame)
@@ -1617,11 +1674,11 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz)
memset(&telegramm, 0, sizeof(telegramm));
- if (cnetz->metering) {
- double now = get_time();
- if (!trans->call_start)
- trans->call_start = now;
- meter = (now - trans->call_start) / (double)cnetz->metering + 1;
+ if (trans->metering_time) {
+ /* get end time. if not set, use current time. (still running) */
+ double end = (trans->meter_end) ? : get_time();
+ /* add one unit, because when metering is started, the first unit is counted. */
+ meter = (end - trans->meter_start) / (double)trans->metering_time + 1.0;
}
telegramm.max_sendeleistung = cnetz_power2bits(cnetz->ms_power);
@@ -1634,7 +1691,7 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz)
telegramm.futln_nationalitaet = trans->futln_nat;
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
telegramm.futln_rest_nr = trans->futln_rest;
- telegramm.frequenz_nr = atoi(cnetz->sender.kanal);
+ telegramm.frequenz_nr = cnetz->kanal;
telegramm.entfernung = si.entfernung;
telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit;
telegramm.gueltigkeit_des_gebuehrenstandes = 0;
@@ -1643,15 +1700,15 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz)
switch (trans->state) {
case TRANS_VHQ_V:
if ((cnetz->sched_ts & 8) == 0) { /* sub frame 1 and 3 */
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Quittung Verbindung halten 1' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Quittung Verbindung halten 1' on traffic channel\n");
telegramm.opcode = OPCODE_VHQ1_V;
} else { /* sub frame 2 and 4 */
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Quittung Verbindung halten 2' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Quittung Verbindung halten 2' on traffic channel\n");
telegramm.opcode = OPCODE_VHQ2_V;
}
break;
case TRANS_AF:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n");
telegramm.opcode = OPCODE_AF_V;
if (++trans->repeat == N_AFV) {
destroy_transaction(trans);
@@ -1659,7 +1716,7 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz)
}
break;
case TRANS_AT:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledge to 'Ausloesen durch FuTln' on traffic channel\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledge to 'Ausloesen durch FuTln' on traffic channel\n");
telegramm.opcode = OPCODE_AF_V;
if (++trans->repeat == 1) {
destroy_transaction(trans);
@@ -1693,16 +1750,16 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm)
}
if (trans->state != TRANS_VHQ_V)
break;
- timer_start(&trans->timer, 0.6 * F_VHQ); /* F_VHQ frames */
+ osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.6 * F_VHQ)); /* F_VHQ frames */
switch (opcode) {
case OPCODE_VH_V:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received supervisory frame 'Verbindung halten' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received supervisory frame 'Verbindung halten' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
break;
case OPCODE_USAI_V:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received internal handover request frame 'Umschaltantrag intern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received internal handover request frame 'Umschaltantrag intern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
break;
case OPCODE_USAE_V:
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received external handover request frame 'Umschaltantrag extern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received external handover request frame 'Umschaltantrag extern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
break;
}
valid_frame = 1;
@@ -1723,21 +1780,21 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm)
if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) {
break;
}
- PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received release frame 'Ausloesen durch FuTln' message.\n");
+ LOGP_CHAN(DCNETZ, LOGL_INFO, "Received release frame 'Ausloesen durch FuTln' message.\n");
valid_frame = 1;
/* if already received this frame, if we are releasing */
if (trans->state == TRANS_AT || trans->state == TRANS_AF)
break;
trans_new_state(trans, TRANS_AT);
trans->repeat = 0;
- timer_stop(&trans->timer);
+ osmo_timer_del(&trans->timer);
if (trans->callref) {
call_up_release(trans->callref, CAUSE_NORMAL);
trans->callref = 0;
}
break;
default:
- PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode));
+ LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode));
}
if (valid_frame)