C-Netz: Add tiny database to track if phones are online
Reject calls, if not online. Use an interval to check if the phones are still online.
This commit is contained in:
@@ -5,6 +5,7 @@ bin_PROGRAMS = \
|
|||||||
|
|
||||||
cnetz_SOURCES = \
|
cnetz_SOURCES = \
|
||||||
cnetz.c \
|
cnetz.c \
|
||||||
|
database.c \
|
||||||
sysinfo.c \
|
sysinfo.c \
|
||||||
telegramm.c \
|
telegramm.c \
|
||||||
dsp.c \
|
dsp.c \
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "../common/call.h"
|
#include "../common/call.h"
|
||||||
#include "../common/cause.h"
|
#include "../common/cause.h"
|
||||||
#include "cnetz.h"
|
#include "cnetz.h"
|
||||||
|
#include "database.h"
|
||||||
#include "sysinfo.h"
|
#include "sysinfo.h"
|
||||||
#include "telegramm.h"
|
#include "telegramm.h"
|
||||||
#include "dsp.h"
|
#include "dsp.h"
|
||||||
@@ -367,7 +368,13 @@ inval:
|
|||||||
futln_fuvst = dialing[1] - '0';
|
futln_fuvst = dialing[1] - '0';
|
||||||
futln_rest = atoi(dialing + 2);
|
futln_rest = atoi(dialing + 2);
|
||||||
|
|
||||||
/* 2. check if given number is already in a call, return BUSY */
|
/* 2. check if the subscriber is attached */
|
||||||
|
if (!find_db(futln_nat, futln_fuvst, futln_rest)) {
|
||||||
|
PDEBUG(DCNETZ, DEBUG_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) {
|
for (sender = sender_head; sender; sender = sender->next) {
|
||||||
cnetz = (cnetz_t *) sender;
|
cnetz = (cnetz_t *) sender;
|
||||||
/* search transaction for this number */
|
/* search transaction for this number */
|
||||||
@@ -386,12 +393,13 @@ inval:
|
|||||||
return -CAUSE_BUSY;
|
return -CAUSE_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. check if all senders are busy, return NOCHANNEL */
|
/* 4. check if all senders are busy, return NOCHANNEL */
|
||||||
if (!search_free_spk()) {
|
if (!search_free_spk()) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
|
||||||
return -CAUSE_NOCHANNEL;
|
return -CAUSE_NOCHANNEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 5. check if we have no OgK, return NOCHANNEL */
|
||||||
cnetz = search_ogk();
|
cnetz = search_ogk();
|
||||||
if (!cnetz) {
|
if (!cnetz) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n");
|
||||||
@@ -400,7 +408,7 @@ inval:
|
|||||||
|
|
||||||
PDEBUG(DCNETZ, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
|
PDEBUG(DCNETZ, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
|
||||||
|
|
||||||
/* 4. trying to page mobile station */
|
/* 6. trying to page mobile station */
|
||||||
cnetz->sender.callref = callref;
|
cnetz->sender.callref = callref;
|
||||||
|
|
||||||
trans = create_transaction(cnetz, TRANS_VAK, dialing[0] - '0', dialing[1] - '0', atoi(dialing + 2));
|
trans = create_transaction(cnetz, TRANS_VAK, dialing[0] - '0', dialing[1] - '0', atoi(dialing + 2));
|
||||||
@@ -514,6 +522,25 @@ void call_out_release(int callref, int cause)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest)
|
||||||
|
{
|
||||||
|
cnetz_t *cnetz;
|
||||||
|
transaction_t *trans;
|
||||||
|
|
||||||
|
cnetz = search_ogk();
|
||||||
|
if (!cnetz) {
|
||||||
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "'Meldeaufruf', but OgK is currently busy, rejecting!\n");
|
||||||
|
return -CAUSE_NOCHANNEL;
|
||||||
|
}
|
||||||
|
trans = create_transaction(cnetz, TRANS_MA, futln_nat, futln_fuvst, futln_rest);
|
||||||
|
if (!trans) {
|
||||||
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||||
|
return -CAUSE_TEMPFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transaction handling
|
* Transaction handling
|
||||||
*/
|
*/
|
||||||
@@ -575,6 +602,9 @@ static transaction_t *create_transaction(cnetz_t *cnetz, uint32_t state, uint8_t
|
|||||||
|
|
||||||
link_transaction(trans, cnetz);
|
link_transaction(trans, cnetz);
|
||||||
|
|
||||||
|
/* update database: now busy */
|
||||||
|
update_db(cnetz, futln_nat, futln_fuvst, futln_rest, 1, 0);
|
||||||
|
|
||||||
return trans;
|
return trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,6 +628,9 @@ static void unlink_transaction(transaction_t *trans)
|
|||||||
/* destroy transaction */
|
/* destroy transaction */
|
||||||
static void destroy_transaction(transaction_t *trans)
|
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);
|
unlink_transaction(trans);
|
||||||
|
|
||||||
const char *rufnummer = transaction2rufnummer(trans);
|
const char *rufnummer = transaction2rufnummer(trans);
|
||||||
@@ -626,6 +659,24 @@ static transaction_t *search_transaction(cnetz_t *cnetz, uint32_t state_mask)
|
|||||||
return NULL;
|
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)
|
static const char *trans_state_name(int state)
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -637,6 +688,8 @@ static const char *trans_state_name(int state)
|
|||||||
return "UM";
|
return "UM";
|
||||||
case TRANS_MA:
|
case TRANS_MA:
|
||||||
return "MA";
|
return "MA";
|
||||||
|
case TRANS_MFT:
|
||||||
|
return "MFT";
|
||||||
case TRANS_VWG:
|
case TRANS_VWG:
|
||||||
return "VWG";
|
return "VWG";
|
||||||
case TRANS_WAF:
|
case TRANS_WAF:
|
||||||
@@ -743,6 +796,8 @@ static void transaction_timeout(struct timer *timer)
|
|||||||
case TRANS_WAF:
|
case TRANS_WAF:
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "No response after dialing request 'Wahlaufforderung'\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "No response after dialing request 'Wahlaufforderung'\n");
|
||||||
if (++trans->count == 3) {
|
if (++trans->count == 3) {
|
||||||
|
/* no response to dialing is like MA failed */
|
||||||
|
trans->ma_failed = 1;
|
||||||
trans_new_state(trans, TRANS_WBN);
|
trans_new_state(trans, TRANS_WBN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -785,6 +840,10 @@ static void transaction_timeout(struct timer *timer)
|
|||||||
cnetz->sender.callref = 0;
|
cnetz->sender.callref = 0;
|
||||||
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
|
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
|
||||||
break;
|
break;
|
||||||
|
case TRANS_MFT:
|
||||||
|
trans->ma_failed = 1;
|
||||||
|
destroy_transaction(trans);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Timeout unhandled in state %d\n", trans->state);
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Timeout unhandled in state %d\n", trans->state);
|
||||||
}
|
}
|
||||||
@@ -963,7 +1022,7 @@ const telegramm_t *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz)
|
|||||||
telegramm.ogk_vorschlag = CNETZ_OGK_KANAL;
|
telegramm.ogk_vorschlag = CNETZ_OGK_KANAL;
|
||||||
telegramm.fuz_rest_nr = si.fuz_rest;
|
telegramm.fuz_rest_nr = si.fuz_rest;
|
||||||
|
|
||||||
trans = search_transaction(cnetz, TRANS_VWG);
|
trans = search_transaction(cnetz, TRANS_VWG | TRANS_MA);
|
||||||
if (trans) {
|
if (trans) {
|
||||||
switch (trans->state) {
|
switch (trans->state) {
|
||||||
case TRANS_VWG:
|
case TRANS_VWG:
|
||||||
@@ -975,6 +1034,15 @@ const telegramm_t *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz)
|
|||||||
trans_new_state(trans, TRANS_WAF);
|
trans_new_state(trans, TRANS_WAF);
|
||||||
timer_start(&trans->timer, 4.0); /* Wait two slot cycles until resending */
|
timer_start(&trans->timer, 4.0); /* Wait two slot cycles until resending */
|
||||||
break;
|
break;
|
||||||
|
case TRANS_MA:
|
||||||
|
PDEBUG(DCNETZ, DEBUG_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, 4.0); /* Wait two slot cycles until timeout */
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
; /* MLR */
|
; /* MLR */
|
||||||
}
|
}
|
||||||
@@ -1066,6 +1134,15 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
|||||||
trans_new_state(trans, TRANS_WBP);
|
trans_new_state(trans, TRANS_WBP);
|
||||||
valid_frame = 1;
|
valid_frame = 1;
|
||||||
break;
|
break;
|
||||||
|
case OPCODE_MFT_M:
|
||||||
|
trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
|
||||||
|
if (!trans) {
|
||||||
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Received acknowledge 'Meldun Funktelefonteilnemer' message without transaction, ignoring!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
destroy_transaction(trans);
|
||||||
|
valid_frame = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode));
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode));
|
||||||
}
|
}
|
||||||
|
@@ -32,24 +32,25 @@ enum cnetz_state {
|
|||||||
/* roaming to different base station/network */
|
/* roaming to different base station/network */
|
||||||
#define TRANS_UM (1 << 1) /* roaming request received, sending reply */
|
#define TRANS_UM (1 << 1) /* roaming request received, sending reply */
|
||||||
/* check if phone is still on */
|
/* check if phone is still on */
|
||||||
#define TRANS_MA (1 << 2) /* periodic online check sent, waiting for reply */
|
#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 */
|
/* mobile originated call */
|
||||||
#define TRANS_VWG (1 << 3) /* received dialing request, waiting for time slot to send dial order */
|
#define TRANS_VWG (1 << 4) /* received dialing request, waiting for time slot to send dial order */
|
||||||
#define TRANS_WAF (1 << 4) /* dial order sent, waiting for dialing */
|
#define TRANS_WAF (1 << 5) /* dial order sent, waiting for dialing */
|
||||||
#define TRANS_WBP (1 << 5) /* dialing received, waiting for time slot to acknowledge call */
|
#define TRANS_WBP (1 << 6) /* dialing received, waiting for time slot to acknowledge call */
|
||||||
#define TRANS_WBN (1 << 6) /* dialing received, waiting for time slot to reject call */
|
#define TRANS_WBN (1 << 7) /* dialing received, waiting for time slot to reject call */
|
||||||
#define TRANS_VAG (1 << 7) /* establishment of call sent, switching channel */
|
#define TRANS_VAG (1 << 8) /* establishment of call sent, switching channel */
|
||||||
/* mobile terminated call */
|
/* mobile terminated call */
|
||||||
#define TRANS_VAK (1 << 8) /* establishment of call sent, switching channel */
|
#define TRANS_VAK (1 << 9) /* establishment of call sent, switching channel */
|
||||||
/* traffic channel */
|
/* traffic channel */
|
||||||
#define TRANS_BQ (1 << 9) /* accnowledge channel */
|
#define TRANS_BQ (1 << 10) /* accnowledge channel */
|
||||||
#define TRANS_VHQ (1 << 10) /* hold call */
|
#define TRANS_VHQ (1 << 11) /* hold call */
|
||||||
#define TRANS_RTA (1 << 11) /* hold call and make the phone ring */
|
#define TRANS_RTA (1 << 12) /* hold call and make the phone ring */
|
||||||
#define TRANS_DS (1 << 12) /* establish speech connection */
|
#define TRANS_DS (1 << 13) /* establish speech connection */
|
||||||
#define TRANS_AHQ (1 << 13) /* establish speech connection after answer */
|
#define TRANS_AHQ (1 << 14) /* establish speech connection after answer */
|
||||||
/* release */
|
/* release */
|
||||||
#define TRANS_AF (1 << 14) /* release connection by base station */
|
#define TRANS_AF (1 << 15) /* release connection by base station */
|
||||||
#define TRANS_AT (1 << 15) /* release connection by mobile station */
|
#define TRANS_AT (1 << 16) /* release connection by mobile station */
|
||||||
|
|
||||||
/* timers */
|
/* timers */
|
||||||
#define F_BQ 8 /* number of not received frames at BQ state */
|
#define F_BQ 8 /* number of not received frames at BQ state */
|
||||||
@@ -81,6 +82,7 @@ typedef struct transaction {
|
|||||||
struct timer timer; /* for varous timeouts */
|
struct timer timer; /* for varous timeouts */
|
||||||
int mo_call; /* flags a moile originating call */
|
int mo_call; /* flags a moile originating call */
|
||||||
int mt_call; /* flags a moile terminating call */
|
int mt_call; /* flags a moile terminating call */
|
||||||
|
int ma_failed; /* failed to get a response from MS */
|
||||||
} transaction_t;
|
} transaction_t;
|
||||||
|
|
||||||
struct clock_speed {
|
struct clock_speed {
|
||||||
@@ -157,6 +159,7 @@ int cnetz_init(void);
|
|||||||
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], double deviation, double noise, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, int loopback);
|
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], double deviation, double noise, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, int loopback);
|
||||||
void cnetz_destroy(sender_t *sender);
|
void cnetz_destroy(sender_t *sender);
|
||||||
void cnetz_sync_frame(cnetz_t *cnetz, double sync, int ts);
|
void cnetz_sync_frame(cnetz_t *cnetz, double sync, int ts);
|
||||||
|
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
|
||||||
const struct telegramm *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz);
|
const struct telegramm *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz);
|
||||||
const struct telegramm *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz);
|
const struct telegramm *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz);
|
||||||
void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, struct telegramm *telegramm, int block);
|
void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, struct telegramm *telegramm, int block);
|
||||||
|
156
src/cnetz/database.c
Normal file
156
src/cnetz/database.c
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
/* C-Netz database
|
||||||
|
*
|
||||||
|
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../common/debug.h"
|
||||||
|
#include "../common/timer.h"
|
||||||
|
#include "cnetz.h"
|
||||||
|
#include "database.h"
|
||||||
|
|
||||||
|
#define MELDE_INTERVAL 60.0
|
||||||
|
#define MELDE_WIEDERHOLUNG 10.0
|
||||||
|
#define MELDE_MAXIMAL 3
|
||||||
|
|
||||||
|
typedef struct cnetz_database {
|
||||||
|
struct cnetz_database *next;
|
||||||
|
uint8_t futln_nat; /* who ... */
|
||||||
|
uint8_t futln_fuvst;
|
||||||
|
uint16_t futln_rest;
|
||||||
|
struct timer timer; /* timer for next availability check */
|
||||||
|
int retry; /* counts number of retries */
|
||||||
|
} cnetz_db_t;
|
||||||
|
|
||||||
|
cnetz_db_t *cnetz_db_head;
|
||||||
|
|
||||||
|
/* destroy transaction */
|
||||||
|
static void remove_db(cnetz_db_t *db)
|
||||||
|
{
|
||||||
|
cnetz_db_t **dbp;
|
||||||
|
|
||||||
|
/* uinlink */
|
||||||
|
dbp = &cnetz_db_head;
|
||||||
|
while (*dbp && *dbp != db)
|
||||||
|
dbp = &((*dbp)->next);
|
||||||
|
if (!(*dbp)) {
|
||||||
|
PDEBUG(DDB, DEBUG_ERROR, "Transaction not in list, please fix!!\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
*dbp = db->next;
|
||||||
|
|
||||||
|
PDEBUG(DDB, DEBUG_INFO, "Removing subscriber '%d,%d,%d' from database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
|
|
||||||
|
timer_exit(&db->timer);
|
||||||
|
|
||||||
|
free(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Timeout handling */
|
||||||
|
static void db_timeout(struct timer *timer)
|
||||||
|
{
|
||||||
|
cnetz_db_t *db = (cnetz_db_t *)timer->priv;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
PDEBUG(DDB, DEBUG_INFO, "Check, if subscriber '%d,%d,%d' is still available.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
|
|
||||||
|
rc = cnetz_meldeaufruf(db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
|
if (rc < 0) {
|
||||||
|
/* OgK is used for speech, but this never happens in a real
|
||||||
|
* network. We just assume that the phone has responded and
|
||||||
|
* assume we had a response. */
|
||||||
|
PDEBUG(DDB, DEBUG_INFO, "OgK busy, so we assume a positive response.\n");
|
||||||
|
timer_start(&db->timer, MELDE_INTERVAL); /* when to check avaiability again */
|
||||||
|
db->retry = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create/update db entry */
|
||||||
|
void update_db(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int busy, int failed)
|
||||||
|
{
|
||||||
|
cnetz_db_t *db, **dbp;
|
||||||
|
|
||||||
|
/* search transaction for this subsriber */
|
||||||
|
db = cnetz_db_head;
|
||||||
|
while (db) {
|
||||||
|
if (db->futln_nat == futln_nat
|
||||||
|
&& db->futln_fuvst == futln_fuvst
|
||||||
|
&& db->futln_rest == futln_rest)
|
||||||
|
break;
|
||||||
|
db = db->next;
|
||||||
|
}
|
||||||
|
if (!db) {
|
||||||
|
db = calloc(1, sizeof(*db));
|
||||||
|
if (!db) {
|
||||||
|
PDEBUG(DDB, DEBUG_ERROR, "No memory!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timer_init(&db->timer, db_timeout, db);
|
||||||
|
|
||||||
|
db->futln_nat = futln_nat;
|
||||||
|
db->futln_fuvst = futln_fuvst;
|
||||||
|
db->futln_rest = futln_rest;
|
||||||
|
|
||||||
|
/* attach to end of list */
|
||||||
|
dbp = &cnetz_db_head;
|
||||||
|
while (*dbp)
|
||||||
|
dbp = &((*dbp)->next);
|
||||||
|
*dbp = db;
|
||||||
|
|
||||||
|
PDEBUG(DDB, DEBUG_INFO, "Adding subscriber '%d,%d,%d' to database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (busy) {
|
||||||
|
PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%d' busy now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
|
timer_stop(&db->timer);
|
||||||
|
} else if (!failed) {
|
||||||
|
PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%d' idle now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
|
timer_start(&db->timer, MELDE_INTERVAL); /* when to check avaiability (again) */
|
||||||
|
db->retry = 0;
|
||||||
|
} else {
|
||||||
|
if (++db->retry == MELDE_MAXIMAL) {
|
||||||
|
PDEBUG(DDB, DEBUG_NOTICE, "Paging subscriber '%d,%d,%d' failed.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
|
remove_db(db);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timer_start(&db->timer, MELDE_WIEDERHOLUNG); /* when to do retry */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest)
|
||||||
|
{
|
||||||
|
cnetz_db_t *db = cnetz_db_head;
|
||||||
|
|
||||||
|
while (db) {
|
||||||
|
if (db->futln_nat == futln_nat
|
||||||
|
&& db->futln_fuvst == futln_fuvst
|
||||||
|
&& db->futln_rest == futln_rest)
|
||||||
|
return 1;
|
||||||
|
db = db->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_db(void)
|
||||||
|
{
|
||||||
|
while (cnetz_db_head)
|
||||||
|
remove_db(cnetz_db_head);
|
||||||
|
}
|
||||||
|
|
5
src/cnetz/database.h
Normal file
5
src/cnetz/database.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
void update_db(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int busy, int failed);
|
||||||
|
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
|
||||||
|
void flush_db(void);
|
||||||
|
|
@@ -32,6 +32,7 @@
|
|||||||
#include "../common/freiton.h"
|
#include "../common/freiton.h"
|
||||||
#include "../common/besetztton.h"
|
#include "../common/besetztton.h"
|
||||||
#include "cnetz.h"
|
#include "cnetz.h"
|
||||||
|
#include "database.h"
|
||||||
#include "sysinfo.h"
|
#include "sysinfo.h"
|
||||||
#include "dsp.h"
|
#include "dsp.h"
|
||||||
#include "telegramm.h"
|
#include "telegramm.h"
|
||||||
@@ -292,6 +293,8 @@ fail:
|
|||||||
if (use_mncc_sock)
|
if (use_mncc_sock)
|
||||||
mncc_exit();
|
mncc_exit();
|
||||||
|
|
||||||
|
flush_db();
|
||||||
|
|
||||||
/* destroy transceiver instance */
|
/* destroy transceiver instance */
|
||||||
while (sender_head)
|
while (sender_head)
|
||||||
cnetz_destroy(sender_head);
|
cnetz_destroy(sender_head);
|
||||||
|
@@ -43,6 +43,7 @@ struct debug_cat {
|
|||||||
{ "frame", "\033[0;36m" },
|
{ "frame", "\033[0;36m" },
|
||||||
{ "call", "\033[1;37m" },
|
{ "call", "\033[1;37m" },
|
||||||
{ "mncc", "\033[1;32m" },
|
{ "mncc", "\033[1;32m" },
|
||||||
|
{ "database", "\033[0;33m" },
|
||||||
};
|
};
|
||||||
|
|
||||||
int debuglevel = DEBUG_INFO;
|
int debuglevel = DEBUG_INFO;
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#define DFRAME 7
|
#define DFRAME 7
|
||||||
#define DCALL 8
|
#define DCALL 8
|
||||||
#define DMNCC 9
|
#define DMNCC 9
|
||||||
|
#define DDB 10
|
||||||
|
|
||||||
#define PDEBUG(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, fmt, ## arg)
|
#define PDEBUG(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, fmt, ## arg)
|
||||||
void _printdebug(const char *file, const char *function, int line, int cat, int level, const char *fmt, ...);
|
void _printdebug(const char *file, const char *function, int line, int cat, int level, const char *fmt, ...);
|
||||||
|
Reference in New Issue
Block a user