- better handling of the different connections. All connections are
now in a list with the current state. - not completly tested.
This commit is contained in:
parent
6ed19ab980
commit
9db340586a
|
@ -50,10 +50,11 @@ char pppd_version[] = VERSION;
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void handlemessages(void) ;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static capiconn_context *ctx;
|
||||
static capi_connection *conn = 0;
|
||||
static int isconnected = 0;
|
||||
static int connectinprogress = 0;
|
||||
static unsigned applid;
|
||||
#define CM(x) (1<<(x))
|
||||
#define CIPMASK_ALL 0x1FFF03FF
|
||||
|
@ -240,6 +241,179 @@ static STRINGLIST *stringlist_split(char *tosplit, char *seps)
|
|||
return p;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef struct conn {
|
||||
struct conn *next;
|
||||
capi_connection *conn;
|
||||
int type;
|
||||
#define CONNTYPE_OUTGOING 0
|
||||
#define CONNTYPE_INCOMING 1
|
||||
#define CONNTYPE_IGNORE 2
|
||||
#define CONNTYPE_REJECT 3
|
||||
#define CONNTYPE_FOR_CALLBACK 4
|
||||
int inprogress;
|
||||
int isconnected;
|
||||
} CONN;
|
||||
|
||||
static CONN *connections;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static CONN *conn_remember(capi_connection *conn, int type)
|
||||
{
|
||||
CONN *p, **pp;
|
||||
for (pp = &connections; *pp; pp = &(*pp)->next) ;
|
||||
if ((p = (CONN *)malloc(sizeof(CONN))) == 0) {
|
||||
int serrno = errno;
|
||||
fatal("capiplugin: malloc failed - %s (%d)",
|
||||
strerror(serrno), serrno);
|
||||
return 0;
|
||||
}
|
||||
memset(p, 0, sizeof(CONN));
|
||||
p->conn = conn;
|
||||
p->type = type;
|
||||
p->next = 0;
|
||||
switch (type) {
|
||||
case CONNTYPE_OUTGOING:
|
||||
case CONNTYPE_INCOMING:
|
||||
case CONNTYPE_FOR_CALLBACK:
|
||||
p->inprogress = 1;
|
||||
p->isconnected = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*pp = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
static int conn_forget(capi_connection *conn)
|
||||
{
|
||||
CONN **pp, *p;
|
||||
for (pp = &connections; *pp && (*pp)->conn != conn; pp = &(*pp)->next) ;
|
||||
if (*pp) {
|
||||
p = *pp;
|
||||
*pp = (*pp)->next;
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static CONN *conn_find(capi_connection *cp)
|
||||
{
|
||||
CONN *p;
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->conn == cp)
|
||||
return p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static int conn_connected(capi_connection *conn)
|
||||
{
|
||||
CONN *p;
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->conn == conn) {
|
||||
p->isconnected = 1;
|
||||
p->inprogress = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
fatal("capiplugin: connected connection not found ??");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static int conn_incoming_inprogress(void)
|
||||
{
|
||||
CONN *p;
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->type == CONNTYPE_INCOMING)
|
||||
return p->inprogress;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conn_incoming_connected(void)
|
||||
{
|
||||
CONN *p;
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->type == CONNTYPE_INCOMING)
|
||||
return p->isconnected;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conn_incoming_exists(void)
|
||||
{
|
||||
CONN *p;
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->type == CONNTYPE_INCOMING)
|
||||
return p->isconnected || p->inprogress;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static int conn_inprogress(capi_connection *cp)
|
||||
{
|
||||
CONN *p;
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->conn == cp)
|
||||
return p->inprogress;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conn_isconnected(capi_connection *cp)
|
||||
{
|
||||
CONN *p;
|
||||
if (cp) {
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->conn == cp)
|
||||
return p->isconnected;
|
||||
}
|
||||
} else {
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->isconnected)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void disconnectall(void)
|
||||
{
|
||||
time_t t;
|
||||
CONN *p;
|
||||
|
||||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
for (p = connections; p; p = p->next) {
|
||||
if (p->inprogress || p->isconnected) {
|
||||
p->isconnected = p->inprogress = 0;
|
||||
capiconn_disconnect(p->conn, 0);
|
||||
}
|
||||
}
|
||||
t = time(0)+10;
|
||||
do {
|
||||
handlemessages();
|
||||
} while (connections && time(0) < t);
|
||||
|
||||
if (connections)
|
||||
fatal("capiplugin: disconnectall failed");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static int timeoutrunning = 0;
|
||||
|
@ -381,20 +555,25 @@ static void handlemessages(void)
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void dodisconnect(void)
|
||||
static void dodisconnect(capi_connection *cp)
|
||||
{
|
||||
CONN *conn;
|
||||
time_t t;
|
||||
if (!conn)
|
||||
|
||||
if ((conn = conn_find(cp)) == 0)
|
||||
return;
|
||||
(void)capiconn_disconnect(conn, 0);
|
||||
(void)capiconn_disconnect(cp, 0);
|
||||
conn->isconnected = conn->inprogress = 0;
|
||||
|
||||
t = time(0)+10;
|
||||
while (conn && time(0) < t)
|
||||
do {
|
||||
handlemessages();
|
||||
if (conn)
|
||||
} while (conn_find(cp) && time(0) < t);
|
||||
|
||||
if (conn_find(cp))
|
||||
fatal("capiplugin: timeout while waiting for disconnect");
|
||||
}
|
||||
|
||||
|
||||
static void init_capiconn(void)
|
||||
{
|
||||
static int init = 0;
|
||||
|
@ -716,14 +895,23 @@ static void disconnected(capi_connection *cp,
|
|||
unsigned reason,
|
||||
unsigned reason_b3)
|
||||
{
|
||||
if (conn != cp) {
|
||||
dbglog("capiplugin: ignored/rejected call disconnected");
|
||||
CONN *p;
|
||||
|
||||
if ((p = conn_find(cp)) == 0)
|
||||
return;
|
||||
conn_forget(cp);
|
||||
switch (p->type) {
|
||||
case CONNTYPE_OUTGOING:
|
||||
case CONNTYPE_INCOMING:
|
||||
break;
|
||||
case CONNTYPE_IGNORE:
|
||||
case CONNTYPE_REJECT:
|
||||
return;
|
||||
case CONNTYPE_FOR_CALLBACK:
|
||||
dreason = reason;
|
||||
break;
|
||||
|
||||
}
|
||||
conn = 0;
|
||||
connectinprogress = 0;
|
||||
isconnected = 0;
|
||||
dreason = reason;
|
||||
if (reason != 0x3304 || debug) /* Another Applikation got the call */
|
||||
info("capiplugin: disconnect(%s): %s 0x%04x (0x%04x) - %s",
|
||||
localdisconnect ? "local" : "remote",
|
||||
|
@ -744,8 +932,9 @@ static void incoming(capi_connection *cp,
|
|||
|
||||
info("capiplugin: incoming call: %s (0x%x)", conninfo(cp), cipvalue);
|
||||
|
||||
if (conn) {
|
||||
info("capiplugin: ignoring call, conn != NULL");
|
||||
if (conn_incoming_exists()) {
|
||||
info("capiplugin: ignoring call, incoming connection exists");
|
||||
conn_remember(cp, CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
|
@ -759,6 +948,7 @@ static void incoming(capi_connection *cp,
|
|||
if (!p) {
|
||||
info("capiplugin: ignoring call, msn %s not in \"%s\"",
|
||||
callednumber, opt_inmsn);
|
||||
conn_remember(cp, CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
|
@ -767,6 +957,7 @@ static void incoming(capi_connection *cp,
|
|||
|| strcmp(s, opt_msn) != 0) {
|
||||
info("capiplugin: ignoring call, msn mismatch (%s != %s)",
|
||||
opt_msn, callednumber);
|
||||
conn_remember(cp, CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
|
@ -781,6 +972,7 @@ static void incoming(capi_connection *cp,
|
|||
if (!p) {
|
||||
info("capiplugin: ignoring call, cli mismatch (%s != %s)",
|
||||
opt_cli, callingnumber);
|
||||
conn_remember(cp, CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
|
@ -793,6 +985,7 @@ static void incoming(capi_connection *cp,
|
|||
if (!p) {
|
||||
info("capiplugin: ignoring call, number mismatch (%s != %s)",
|
||||
opt_number, callingnumber);
|
||||
conn_remember(cp, CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
|
@ -820,6 +1013,7 @@ static void incoming(capi_connection *cp,
|
|||
} else {
|
||||
info("capiplugin: ignoring speech call from %s",
|
||||
callingnumber);
|
||||
conn_remember(cp,CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
}
|
||||
break;
|
||||
|
@ -840,17 +1034,20 @@ static void incoming(capi_connection *cp,
|
|||
} else {
|
||||
info("capiplugin: ignoring digital call from %s",
|
||||
callingnumber);
|
||||
conn_remember(cp,CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
}
|
||||
break;
|
||||
case 17: /* Group 2/3 facsimile */
|
||||
info("capiplugin: ignoring fax call from %s",
|
||||
callingnumber);
|
||||
conn_remember(cp,CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
break;
|
||||
default:
|
||||
info("capiplugin: ignoring type %d call from %s",
|
||||
cipvalue, callingnumber);
|
||||
conn_remember(cp,CONNTYPE_IGNORE);
|
||||
(void) capiconn_ignore(cp);
|
||||
break;
|
||||
}
|
||||
|
@ -859,12 +1056,14 @@ static void incoming(capi_connection *cp,
|
|||
callback:
|
||||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
dbglog("capiplugin: rejecting call: %s (0x%x)", conninfo(cp), cipvalue);
|
||||
conn_remember(cp, CONNTYPE_REJECT);
|
||||
capiconn_reject(cp);
|
||||
makecallback();
|
||||
return;
|
||||
|
||||
wakeupdemand:
|
||||
dbglog("capiplugin: rejecting call: %s (0x%x)", conninfo(cp), cipvalue);
|
||||
conn_remember(cp, CONNTYPE_REJECT);
|
||||
capiconn_reject(cp);
|
||||
wakeupdemand();
|
||||
return;
|
||||
|
@ -887,8 +1086,7 @@ accept:
|
|||
} else { /* hdlc */
|
||||
(void) capiconn_accept(cp, 0, 1, 0, 0, 0, 0, 0);
|
||||
}
|
||||
conn = cp;
|
||||
connectinprogress = 1;
|
||||
conn_remember(cp, CONNTYPE_INCOMING);
|
||||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
@ -939,8 +1137,7 @@ static void connected(capi_connection *cp, _cstruct NCPI)
|
|||
sprintf(buf, "%d", p->b2proto); _script_setenv("B2PROTOCOL", buf);
|
||||
sprintf(buf, "%d", p->b3proto); _script_setenv("B3PROTOCOL", buf);
|
||||
|
||||
isconnected = 1;
|
||||
connectinprogress = 0;
|
||||
conn_connected(cp);
|
||||
if (wakeupneeded)
|
||||
wakeupdemand();
|
||||
}
|
||||
|
@ -984,15 +1181,16 @@ capiconn_callbacks callbacks = {
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void setupconnection(char *num, int awaitingreject)
|
||||
static capi_connection *setupconnection(char *num, int awaitingreject)
|
||||
{
|
||||
struct capi_connection *cp;
|
||||
char number[256];
|
||||
|
||||
snprintf(number, sizeof(number), "%s%s",
|
||||
opt_numberprefix ? opt_numberprefix : "", num);
|
||||
|
||||
if (proto == PROTO_HDLC) {
|
||||
conn = capiconn_connect(ctx,
|
||||
cp = capiconn_connect(ctx,
|
||||
controller, /* contr */
|
||||
2, /* cipvalue */
|
||||
opt_channels ? 0 : number,
|
||||
|
@ -1002,7 +1200,7 @@ static void setupconnection(char *num, int awaitingreject)
|
|||
opt_channels ? AdditionalInfo : 0,
|
||||
0);
|
||||
} else if (proto == PROTO_X75) {
|
||||
conn = capiconn_connect(ctx,
|
||||
cp = capiconn_connect(ctx,
|
||||
controller, /* contr */
|
||||
2, /* cipvalue */
|
||||
opt_channels ? 0 : number,
|
||||
|
@ -1012,7 +1210,7 @@ static void setupconnection(char *num, int awaitingreject)
|
|||
opt_channels ? AdditionalInfo : 0,
|
||||
0);
|
||||
} else if (proto == PROTO_V42BIS) {
|
||||
conn = capiconn_connect(ctx,
|
||||
cp = capiconn_connect(ctx,
|
||||
controller, /* contr */
|
||||
2, /* cipvalue */
|
||||
opt_channels ? 0 : number,
|
||||
|
@ -1022,7 +1220,7 @@ static void setupconnection(char *num, int awaitingreject)
|
|||
opt_channels ? AdditionalInfo : 0,
|
||||
0);
|
||||
} else if (proto == PROTO_MODEM) {
|
||||
conn = capiconn_connect(ctx,
|
||||
cp = capiconn_connect(ctx,
|
||||
controller, /* contr */
|
||||
1, /* cipvalue */
|
||||
opt_channels ? 0 : number,
|
||||
|
@ -1033,7 +1231,7 @@ static void setupconnection(char *num, int awaitingreject)
|
|||
0);
|
||||
} else {
|
||||
fatal("capiplugin: unknown protocol \"%s\"", opt_proto);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (opt_channels) {
|
||||
info("capiplugin: leased line (%s)",
|
||||
|
@ -1044,26 +1242,31 @@ static void setupconnection(char *num, int awaitingreject)
|
|||
info("capiplugin: dialing %s (%s)",
|
||||
number, opt_proto ? opt_proto : "hdlc");
|
||||
}
|
||||
connectinprogress = 1;
|
||||
if (awaitingreject)
|
||||
conn_remember(cp, CONNTYPE_FOR_CALLBACK);
|
||||
else
|
||||
conn_remember(cp, CONNTYPE_OUTGOING);
|
||||
return cp;
|
||||
}
|
||||
|
||||
static void makeleasedline(void)
|
||||
{
|
||||
capi_connection *cp;
|
||||
time_t t;
|
||||
|
||||
setupconnection("", 0);
|
||||
cp = setupconnection("", 0);
|
||||
|
||||
t = time(0)+opt_dialtimeout;
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK && conn)
|
||||
dodisconnect();
|
||||
} while (time(0) < t && conn && !isconnected);
|
||||
if (status != EXIT_OK && conn_find(cp))
|
||||
dodisconnect(cp);
|
||||
} while (time(0) < t && conn_inprogress(cp));
|
||||
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
|
||||
if (conn && isconnected) {
|
||||
if (conn_isconnected(cp)) {
|
||||
t = time(0)+opt_connectdelay;
|
||||
do {
|
||||
handlemessages();
|
||||
|
@ -1073,12 +1276,13 @@ static void makeleasedline(void)
|
|||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
|
||||
if (!conn)
|
||||
if (!conn_isconnected(cp))
|
||||
fatal("capiplugin: couldn't make connection");
|
||||
}
|
||||
|
||||
static void makeconnection(STRINGLIST *numbers)
|
||||
{
|
||||
capi_connection *cp = 0;
|
||||
time_t t;
|
||||
STRINGLIST *p;
|
||||
int retry = 0;
|
||||
|
@ -1094,37 +1298,39 @@ static void makeconnection(STRINGLIST *numbers)
|
|||
} while (time(0) < t);
|
||||
}
|
||||
|
||||
setupconnection(p->s, 0);
|
||||
cp = setupconnection(p->s, 0);
|
||||
|
||||
t = time(0)+opt_dialtimeout;
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK && conn)
|
||||
dodisconnect();
|
||||
} while (time(0) < t && conn && !isconnected);
|
||||
if (status != EXIT_OK && conn_find(cp))
|
||||
dodisconnect(cp);
|
||||
} while (time(0) < t && conn_inprogress(cp));
|
||||
|
||||
if (conn && isconnected)
|
||||
if (conn_isconnected(cp))
|
||||
goto connected;
|
||||
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
}
|
||||
} while (++retry < opt_dialmax);
|
||||
|
||||
connected:
|
||||
if (conn && isconnected) {
|
||||
if (conn_isconnected(cp)) {
|
||||
t = time(0)+opt_connectdelay;
|
||||
do {
|
||||
handlemessages();
|
||||
} while (time(0) < t);
|
||||
}
|
||||
|
||||
if (!conn)
|
||||
if (!conn_isconnected(cp))
|
||||
fatal("capiplugin: couldn't make connection after %d retries",
|
||||
retry);
|
||||
}
|
||||
|
||||
static void makeconnection_with_callback(void)
|
||||
{
|
||||
capi_connection *cp;
|
||||
STRINGLIST *p;
|
||||
time_t t;
|
||||
int retry = 0;
|
||||
|
@ -1142,7 +1348,7 @@ again:
|
|||
} while (time(0) < t);
|
||||
}
|
||||
|
||||
setupconnection(p->s, 1);
|
||||
cp = setupconnection(p->s, 1);
|
||||
|
||||
/* Wait specific time for the server rejecting the call */
|
||||
t = time(0)+opt_dialtimeout;
|
||||
|
@ -1150,10 +1356,10 @@ again:
|
|||
handlemessages();
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
} while (time(0) < t && conn && !isconnected);
|
||||
} while (time(0) < t && conn_inprogress(cp));
|
||||
|
||||
if (conn) {
|
||||
dodisconnect();
|
||||
if (conn_isconnected(cp)) {
|
||||
dodisconnect(cp);
|
||||
fatal("capiplugin: callback failed - other side answers the call (no reject)");
|
||||
} else if (was_no_reject()) {
|
||||
goto again;
|
||||
|
@ -1169,9 +1375,9 @@ again:
|
|||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
die(status);
|
||||
}
|
||||
} while (!isconnected && time(0) < t);
|
||||
} while (!conn_incoming_connected() && time(0) < t);
|
||||
|
||||
if (isconnected) {
|
||||
if (conn_incoming_connected()) {
|
||||
add_fd(capi20_fileno(applid));
|
||||
setup_timeout();
|
||||
return;
|
||||
|
@ -1212,17 +1418,17 @@ static void waitforcall(void)
|
|||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
die(status);
|
||||
}
|
||||
if (connectinprogress) try=1;
|
||||
if (try && !connectinprogress) {
|
||||
if (conn_incoming_inprogress()) try=1;
|
||||
if (try && !conn_incoming_inprogress()) {
|
||||
try = 0;
|
||||
if (!isconnected) {
|
||||
if (!conn_incoming_connected()) {
|
||||
(void) capiconn_listen(ctx, controller, cipmask, 0);
|
||||
info("capiplugin: waiting for incoming call ...");
|
||||
}
|
||||
}
|
||||
} while (!isconnected);
|
||||
} while (!conn_incoming_connected());
|
||||
|
||||
if (conn && isconnected) {
|
||||
if (conn_incoming_connected()) {
|
||||
time_t t = time(0)+opt_connectdelay;
|
||||
do {
|
||||
handlemessages();
|
||||
|
@ -1244,7 +1450,7 @@ static int capi_new_phase_hook(int phase)
|
|||
if ((fd = capi20_fileno(applid)) >= 0)
|
||||
remove_fd(fd);
|
||||
unsetup_timeout();
|
||||
dodisconnect();
|
||||
disconnectall();
|
||||
break;
|
||||
case PHASE_INITIALIZE:
|
||||
info("capiplugin: phase initialize");
|
||||
|
@ -1260,7 +1466,7 @@ static int capi_new_phase_hook(int phase)
|
|||
case PHASE_SERIALCONN:
|
||||
info("capiplugin: phase serialconn%s",
|
||||
opt_cbflag ? " (callback)" : "");
|
||||
if (isconnected)
|
||||
if (conn_isconnected(0))
|
||||
break;
|
||||
plugin_check_options();
|
||||
init_capiconn();
|
||||
|
|
Loading…
Reference in New Issue