2016-05-08 13:34:14 +00:00
|
|
|
/* 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>
|
2017-11-18 07:06:06 +00:00
|
|
|
#include "../libsample/sample.h"
|
2017-11-18 07:58:57 +00:00
|
|
|
#include "../libdebug/debug.h"
|
2016-05-08 13:34:14 +00:00
|
|
|
#include "cnetz.h"
|
|
|
|
#include "database.h"
|
|
|
|
|
2016-10-23 05:32:21 +00:00
|
|
|
/* the network specs say: check every 1 - 6.5 minutes for availability
|
|
|
|
* remove from database after 3 subsequent failures
|
|
|
|
* the phone will register 20 minutes after no call / no paging from network.
|
|
|
|
*/
|
|
|
|
#define MELDE_INTERVAL 120.0
|
|
|
|
#define MELDE_WIEDERHOLUNG 60.0
|
2016-05-08 13:34:14 +00:00
|
|
|
#define MELDE_MAXIMAL 3
|
|
|
|
|
|
|
|
typedef struct cnetz_database {
|
2017-08-26 15:48:13 +00:00
|
|
|
|
2016-05-08 13:34:14 +00:00
|
|
|
struct cnetz_database *next;
|
|
|
|
uint8_t futln_nat; /* who ... */
|
|
|
|
uint8_t futln_fuvst;
|
|
|
|
uint16_t futln_rest;
|
2019-06-29 05:49:28 +00:00
|
|
|
int futelg_bit; /* chip card inside */
|
2016-08-03 06:44:13 +00:00
|
|
|
int extended; /* mobile supports extended frequencies */
|
2016-05-08 13:34:14 +00:00
|
|
|
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)) {
|
2017-05-17 18:14:37 +00:00
|
|
|
PDEBUG(DDB, DEBUG_ERROR, "Subscriber not in list, please fix!!\n");
|
2016-05-08 13:34:14 +00:00
|
|
|
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 */
|
2019-06-29 05:49:28 +00:00
|
|
|
int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended, int busy, int failed)
|
2016-05-08 13:34:14 +00:00
|
|
|
{
|
|
|
|
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");
|
2016-08-03 06:44:13 +00:00
|
|
|
return 0;
|
2016-05-08 13:34:14 +00:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-06-29 05:49:28 +00:00
|
|
|
if (futelg_bit && *futelg_bit >= 0)
|
|
|
|
db->futelg_bit = *futelg_bit;
|
|
|
|
|
|
|
|
if (extended && *extended >= 0)
|
|
|
|
db->extended = *extended;
|
2016-08-03 06:44:13 +00:00
|
|
|
|
2016-05-08 13:34:14 +00:00
|
|
|
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 {
|
2016-05-10 17:25:58 +00:00
|
|
|
db->retry++;
|
|
|
|
PDEBUG(DDB, DEBUG_NOTICE, "Paging subscriber '%d,%d,%d' failed (try %d of %d).\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->retry, MELDE_MAXIMAL);
|
|
|
|
if (db->retry == MELDE_MAXIMAL) {
|
2016-05-08 13:34:14 +00:00
|
|
|
remove_db(db);
|
2016-08-03 06:44:13 +00:00
|
|
|
return db->extended;
|
2016-05-08 13:34:14 +00:00
|
|
|
}
|
|
|
|
timer_start(&db->timer, MELDE_WIEDERHOLUNG); /* when to do retry */
|
|
|
|
}
|
2016-08-03 06:44:13 +00:00
|
|
|
|
2019-06-29 05:49:28 +00:00
|
|
|
if (futelg_bit)
|
|
|
|
*futelg_bit = db->futelg_bit;
|
|
|
|
if (extended)
|
|
|
|
*extended = db->extended;
|
|
|
|
return 0;
|
2016-05-08 13:34:14 +00:00
|
|
|
}
|
|
|
|
|
2019-06-29 05:49:28 +00:00
|
|
|
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended)
|
2016-05-08 13:34:14 +00:00
|
|
|
{
|
|
|
|
cnetz_db_t *db = cnetz_db_head;
|
|
|
|
|
|
|
|
while (db) {
|
|
|
|
if (db->futln_nat == futln_nat
|
|
|
|
&& db->futln_fuvst == futln_fuvst
|
2019-06-29 05:49:28 +00:00
|
|
|
&& db->futln_rest == futln_rest) {
|
|
|
|
if (futelg_bit)
|
|
|
|
*futelg_bit = db->futelg_bit;
|
|
|
|
if (extended)
|
|
|
|
*extended = db->extended;
|
|
|
|
return 0;
|
|
|
|
}
|
2016-05-08 13:34:14 +00:00
|
|
|
db = db->next;
|
|
|
|
}
|
2017-08-26 15:48:13 +00:00
|
|
|
return -1;
|
2016-05-08 13:34:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void flush_db(void)
|
|
|
|
{
|
|
|
|
while (cnetz_db_head)
|
|
|
|
remove_db(cnetz_db_head);
|
|
|
|
}
|
|
|
|
|
2016-08-02 07:03:46 +00:00
|
|
|
void dump_db(void)
|
|
|
|
{
|
|
|
|
cnetz_db_t *db = cnetz_db_head;
|
|
|
|
|
|
|
|
PDEBUG(DDB, DEBUG_NOTICE, "Dump of subscriber database:\n");
|
|
|
|
if (!db) {
|
|
|
|
PDEBUG(DDB, DEBUG_NOTICE, " - No subscribers attached!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (db) {
|
|
|
|
PDEBUG(DDB, DEBUG_NOTICE, " - Subscriber '%d,%d,%d' is attached.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
|
|
|
db = db->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|