Inform all applications about incoming calls before handling responses
Implement a method to disable temporary messages from applications to synchronize the delivery of a incoming call. It is important, that all listening application get informed before the first answer was handled. Signed-off-by: Karsten Keil <keil@b1-systems.de>
This commit is contained in:
parent
469b9b5f6b
commit
2f83a0448f
144
capi20/daemon.c
144
capi20/daemon.c
|
@ -50,7 +50,7 @@ extern int ptsname_r(int fd, char *buf, size_t buflen);
|
|||
#define DEF_CONFIG_FILE "/etc/capi20.conf"
|
||||
#endif
|
||||
|
||||
#define MISDNCAPID_VERSION "0.9"
|
||||
#define MISDNCAPID_VERSION "1.0"
|
||||
|
||||
typedef enum {
|
||||
PIT_None = 0,
|
||||
|
@ -69,7 +69,6 @@ struct pollInfo {
|
|||
void *data;
|
||||
};
|
||||
|
||||
#define MI_CONTROL_SHUTDOWN 0x01000000
|
||||
/* give 5 sec periode to allow releasing all applications */
|
||||
#define MI_SHUTDOWN_DELAY 5000
|
||||
|
||||
|
@ -300,19 +299,48 @@ err:
|
|||
return nr_controller;
|
||||
}
|
||||
|
||||
int send_master_control(int event, int len, void *para)
|
||||
{
|
||||
int ret, err, *msg, totlen = sizeof(event);
|
||||
|
||||
if (len > 0) {
|
||||
totlen += len;
|
||||
msg = malloc(totlen);
|
||||
if (!msg) {
|
||||
eprint("Cannot alloc %d bytes for maincontrol message\n", totlen);
|
||||
return -ENOMEM;
|
||||
}
|
||||
*msg = event | len;
|
||||
msg++;
|
||||
memcpy(msg, para, len);
|
||||
msg--;
|
||||
} else {
|
||||
msg = &event;
|
||||
}
|
||||
ret = write(mIControl[1], msg, totlen);
|
||||
if (ret != totlen) {
|
||||
if (ret < 0)
|
||||
err = errno;
|
||||
else
|
||||
err = EMSGSIZE;
|
||||
eprint("Cannot send maincontrol message %08x return %d (%d) - %s\n", *msg, ret, totlen, strerror(err));
|
||||
ret = -err;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
if (len > 0)
|
||||
free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Signal handler for clean shutdown
|
||||
***********************************************************************/
|
||||
static void
|
||||
termHandler(int sig)
|
||||
{
|
||||
int ret, contr = MI_CONTROL_SHUTDOWN;
|
||||
|
||||
iprint("Terminating on signal %d -- request shutdown mISDNcapid\n", sig);
|
||||
|
||||
ret = write(mIControl[1], &contr, sizeof(contr));
|
||||
if (ret != sizeof(contr))
|
||||
eprint("Error sending shutdown to mainloop after signal %d - %s\n", sig, strerror(errno));
|
||||
send_master_control(MICD_CTRL_SHUTDOWN, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -483,6 +511,23 @@ static int del_mainpoll(int fd)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int modify_mainpoll(int enable, int fd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mainpoll_max; i++) {
|
||||
if (mainpoll[i].fd == fd) {
|
||||
if (enable)
|
||||
mainpoll[i].events = POLLIN | POLLPRI;
|
||||
else
|
||||
mainpoll[i].events = POLLPRI;
|
||||
dprint(MIDEBUG_CONTROLLER, "Mainpoll: fd=%d now %s\n", fd, enable ? "enabled" : "disabled");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int mIcapi_mainpoll_releaseApp(int fd, int newfd)
|
||||
{
|
||||
int i;
|
||||
|
@ -501,6 +546,63 @@ int mIcapi_mainpoll_releaseApp(int fd, int newfd)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int main_control(int idx)
|
||||
{
|
||||
int ret, event, len, *fds;
|
||||
void *para = NULL;
|
||||
|
||||
len = sizeof(event);
|
||||
ret = read(mainpoll[idx].fd, &event, len);
|
||||
|
||||
if (ret != len) {
|
||||
if (ret > 0)
|
||||
event = -EMSGSIZE;
|
||||
else
|
||||
event = -errno;
|
||||
eprint("Event for MasterControl read error read return %d (%d) - %s\n", ret, len, strerror(-event));
|
||||
return event;
|
||||
}
|
||||
len = event & MICD_EV_LEN;
|
||||
if (len) {
|
||||
para = malloc(len);
|
||||
if (!para) {
|
||||
eprint("Event for MasterControl cannot alloc %d bytes for parameter\n", len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = read(mainpoll[idx].fd, para, len);
|
||||
if (ret != len) {
|
||||
if (ret > 0)
|
||||
event = -EMSGSIZE;
|
||||
else
|
||||
event = -errno;
|
||||
eprint("Event for MasterControl read error read on parameter return %d (%d) - %s\n", ret, len, strerror(-event));
|
||||
return event;
|
||||
}
|
||||
}
|
||||
switch (event & MICD_EV_MASK) {
|
||||
case MICD_CTRL_SHUTDOWN:
|
||||
break;
|
||||
case MICD_CTRL_DISABLE_POLL:
|
||||
case MICD_CTRL_ENABLE_POLL:
|
||||
len /= sizeof(int);
|
||||
fds = para;
|
||||
while (len) {
|
||||
ret = modify_mainpoll((event & MICD_EV_MASK) == MICD_CTRL_ENABLE_POLL, *fds);
|
||||
if (ret)
|
||||
wprint("modify_mainpoll for fd=%d failed\n", *fds);
|
||||
len--;
|
||||
fds++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
eprint("Unknown event for MasterControl %08x - ignored\n", event);
|
||||
event = -EINVAL;
|
||||
}
|
||||
if (para)
|
||||
free(para);
|
||||
return event;
|
||||
}
|
||||
|
||||
void clean_all(void)
|
||||
{
|
||||
int i, j;
|
||||
|
@ -1938,21 +2040,17 @@ int main_loop(void)
|
|||
}
|
||||
break;
|
||||
case PIT_Control:
|
||||
res = read(mainpoll[i].fd, &error, sizeof(error));
|
||||
if (res == sizeof(error)) {
|
||||
if (error == MI_CONTROL_SHUTDOWN) {
|
||||
iprint("Pollevent ShutdownRequest\n");
|
||||
polldelay = MI_SHUTDOWN_DELAY;
|
||||
ShutDown = 1;
|
||||
res = ReleaseAllApplications();
|
||||
if (res <= 0) { /* No Apllication or error shutdown now */
|
||||
running = 0;
|
||||
error = res;
|
||||
}
|
||||
} else
|
||||
eprint("Pollevent for MasterControl read %x\n", error);
|
||||
} else
|
||||
eprint("Pollevent for MasterControl read error - %s\n", strerror(errno));
|
||||
res = main_control(i);
|
||||
if (res == MICD_CTRL_SHUTDOWN) {
|
||||
iprint("Pollevent ShutdownRequest\n");
|
||||
polldelay = MI_SHUTDOWN_DELAY;
|
||||
ShutDown = 1;
|
||||
res = ReleaseAllApplications();
|
||||
if (res <= 0) { /* No Apllication or error shutdown now */
|
||||
running = 0;
|
||||
error = res;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIT_ReleasedApp:
|
||||
res = read(mainpoll[i].fd, &error, sizeof(error));
|
||||
|
|
|
@ -50,6 +50,17 @@ extern int WriteWaveFiles;
|
|||
extern char *TempDirectory;
|
||||
extern pid_t gettid(void);
|
||||
|
||||
/* Master control defines */
|
||||
|
||||
#define MICD_EV_MASK 0xffff0000
|
||||
#define MICD_EV_LEN 0x0000ffff
|
||||
#define MICD_CTRL_SHUTDOWN 0x42010000
|
||||
#define MICD_CTRL_DISABLE_POLL 0x42020000
|
||||
#define MICD_CTRL_ENABLE_POLL 0x42030000
|
||||
|
||||
int send_master_control(int, int, void *);
|
||||
|
||||
|
||||
struct mCAPIobj;
|
||||
struct mApplication;
|
||||
struct mPLCI;
|
||||
|
@ -448,7 +459,7 @@ static inline void dump_fax_status(struct BInstance *bi) {};
|
|||
#define MIDEBUG_NCCI_DATA (MC_DEBUG_NCCI_DATA << 24)
|
||||
#define MIDEBUG_CAPIOBJ (MC_DEBUG_CAPIOBJ << 24)
|
||||
|
||||
#define MI_PUT_APPLICATION 0x42000001
|
||||
#define MI_PUT_APPLICATION 0x42000000
|
||||
|
||||
int mIcapi_mainpoll_releaseApp(int, int);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sched.h>
|
||||
#include "m_capi.h"
|
||||
#include "mc_buffer.h"
|
||||
#include <mISDN/q931.h>
|
||||
|
@ -162,7 +163,7 @@ static void plciHandleSetupInd(struct mPLCI *plci, int pr, struct mc_buf *mc)
|
|||
struct lPLCI *lp;
|
||||
uint8_t found = 0;
|
||||
int cause = CAUSE_INCOMPATIBLE_DEST;
|
||||
int ret;
|
||||
int ret, *fds, *cur;
|
||||
|
||||
if (!mc || !mc->l3m) {
|
||||
eprint("%s: SETUP without message\n", CAPIobjIDstr(&plci->cobj));
|
||||
|
@ -179,7 +180,7 @@ static void plciHandleSetupInd(struct mPLCI *plci, int pr, struct mc_buf *mc)
|
|||
lc = container_of(co, struct lController, cobj);
|
||||
if ((lc->CIPmask & CIPmask) || (lc->CIPmask & 1)) {
|
||||
ret = lPLCICreate(&lp, lc, plci);
|
||||
if (!ret) {
|
||||
if (ret == 0) {
|
||||
found++;
|
||||
put_cobj(&lp->cobj);
|
||||
} else {
|
||||
|
@ -190,6 +191,21 @@ static void plciHandleSetupInd(struct mPLCI *plci, int pr, struct mc_buf *mc)
|
|||
}
|
||||
if (plci->cobj.itemcnt) {
|
||||
/* at least one lplci was created */
|
||||
fds = calloc(found, sizeof(int));
|
||||
if (!fds)
|
||||
eprint("%s: cannot allocate fds buffer for %d fd - will crash soon\n", CAPIobjIDstr(&plci->cobj), found);
|
||||
cur = fds;
|
||||
pthread_rwlock_rdlock(&plci->cobj.lock);
|
||||
co = plci->cobj.listhead;
|
||||
while (co) {
|
||||
lp = container_of(co, struct lPLCI, cobj);
|
||||
*cur++ = lp->Appl->fd;
|
||||
co = co->next;
|
||||
}
|
||||
pthread_rwlock_unlock(&plci->cobj.lock);
|
||||
/* disable answers until all controller are informed */
|
||||
send_master_control(MICD_CTRL_DISABLE_POLL, found * sizeof(int), fds);
|
||||
sched_yield(); /* make sure that the disable could be processed */
|
||||
co = get_next_cobj(&plci->cobj, NULL);
|
||||
while (co) {
|
||||
lp = container_of(co, struct lPLCI, cobj);
|
||||
|
@ -200,6 +216,9 @@ static void plciHandleSetupInd(struct mPLCI *plci, int pr, struct mc_buf *mc)
|
|||
cleanup_lPLCI(lp);
|
||||
co = get_next_cobj(&plci->cobj, co);
|
||||
}
|
||||
/* Now enable answers again */
|
||||
send_master_control(MICD_CTRL_ENABLE_POLL, found * sizeof(int), fds);
|
||||
free(fds);
|
||||
}
|
||||
}
|
||||
if (found == 0) {
|
||||
|
|
Loading…
Reference in New Issue