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:
Karsten Keil 2012-09-16 17:32:30 +02:00
parent 469b9b5f6b
commit 2f83a0448f
3 changed files with 154 additions and 26 deletions

View File

@ -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));

View File

@ -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);

View File

@ -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) {