152 lines
3.2 KiB
C
152 lines
3.2 KiB
C
|
/*
|
||
|
Copyright (C) 2010,2011 bg <bg_one@mail.ru>
|
||
|
*/
|
||
|
#include "ast_config.h"
|
||
|
|
||
|
#include <unistd.h>
|
||
|
#include <fcntl.h>
|
||
|
|
||
|
#include <asterisk/utils.h>
|
||
|
|
||
|
#include "cpvt.h"
|
||
|
#include "chan_dongle.h" /* struct pvt */
|
||
|
#include "at_queue.h" /* struct at_queue_task */
|
||
|
#include "mutils.h" /* ITEMS_OF() */
|
||
|
|
||
|
#/* return 0 on success */
|
||
|
// TODO: move to activation time, save resouces
|
||
|
static int init_pipe(int filedes[2])
|
||
|
{
|
||
|
int x;
|
||
|
int rv;
|
||
|
int flags;
|
||
|
|
||
|
rv = pipe(filedes);
|
||
|
if(rv == 0) {
|
||
|
for(x = 0; x < 2; ++x) {
|
||
|
rv = fcntl(filedes[x], F_GETFL);
|
||
|
flags = fcntl(filedes[x], F_GETFD);
|
||
|
if(rv == -1 || flags == -1 || (rv = fcntl(filedes[x], F_SETFL, O_NONBLOCK | rv)) == -1 || (rv = fcntl(filedes[x], F_SETFD, flags | FD_CLOEXEC)) == -1)
|
||
|
goto bad;
|
||
|
}
|
||
|
return 0;
|
||
|
bad:
|
||
|
close(filedes[0]);
|
||
|
close(filedes[1]);
|
||
|
}
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
#/* */
|
||
|
EXPORT_DEF struct cpvt * cpvt_alloc(struct pvt * pvt, int call_idx, unsigned dir, call_state_t state)
|
||
|
{
|
||
|
int filedes[2];
|
||
|
struct cpvt * cpvt = NULL;
|
||
|
|
||
|
if(init_pipe(filedes) == 0)
|
||
|
{
|
||
|
cpvt = ast_calloc (1, sizeof (*cpvt));
|
||
|
if(cpvt)
|
||
|
{
|
||
|
cpvt->pvt = pvt;
|
||
|
cpvt->call_idx = call_idx;
|
||
|
cpvt->state = state;
|
||
|
cpvt->dir = dir;
|
||
|
cpvt->rd_pipe[0] = filedes[0];
|
||
|
cpvt->rd_pipe[1] = filedes[1];
|
||
|
|
||
|
// rb_init (&cpvt->a_write_rb, cpvt->a_write_buf, sizeof (cpvt->a_write_buf));
|
||
|
|
||
|
AST_LIST_INSERT_TAIL(&pvt->chans, cpvt, entry);
|
||
|
if(PVT_NO_CHANS(pvt))
|
||
|
pvt_on_create_1st_channel(pvt);
|
||
|
PVT_STATE(pvt, chansno)++;
|
||
|
PVT_STATE(pvt, chan_count[cpvt->state])++;
|
||
|
|
||
|
|
||
|
|
||
|
ast_debug (3, "[%s] create cpvt for call_idx %d dir %d state '%s'\n", PVT_ID(pvt), call_idx, dir, call_state2str(state));
|
||
|
return cpvt;
|
||
|
}
|
||
|
close(filedes[0]);
|
||
|
close(filedes[1]);
|
||
|
}
|
||
|
|
||
|
return cpvt;
|
||
|
}
|
||
|
|
||
|
#/* */
|
||
|
EXPORT_DEF void cpvt_free(struct cpvt* cpvt)
|
||
|
{
|
||
|
pvt_t * pvt = cpvt->pvt;
|
||
|
struct cpvt * found;
|
||
|
struct at_queue_task * task;
|
||
|
|
||
|
close(cpvt->rd_pipe[1]);
|
||
|
close(cpvt->rd_pipe[0]);
|
||
|
|
||
|
ast_debug (3, "[%s] destroy cpvt for call_idx %d dir %d state '%s' flags %d has%s channel\n", PVT_ID(pvt), cpvt->call_idx, cpvt->dir, call_state2str(cpvt->state), cpvt->flags, cpvt->channel ? "" : "'t");
|
||
|
AST_LIST_TRAVERSE_SAFE_BEGIN(&pvt->chans, found, entry) {
|
||
|
if(found == cpvt)
|
||
|
{
|
||
|
AST_LIST_REMOVE_CURRENT(entry);
|
||
|
PVT_STATE(pvt, chan_count[cpvt->state])--;
|
||
|
PVT_STATE(pvt, chansno) --;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
AST_LIST_TRAVERSE_SAFE_END;
|
||
|
|
||
|
/* relink task to sys_chan */
|
||
|
AST_LIST_TRAVERSE(&pvt->at_queue, task, entry) {
|
||
|
if(task->cpvt == cpvt)
|
||
|
{
|
||
|
task->cpvt = &pvt->sys_chan;
|
||
|
}
|
||
|
}
|
||
|
/* drop last_dialed_cpvt if need */
|
||
|
if(pvt->last_dialed_cpvt == cpvt)
|
||
|
pvt->last_dialed_cpvt = NULL;
|
||
|
|
||
|
if(PVT_NO_CHANS(pvt)) {
|
||
|
pvt_on_remove_last_channel(pvt);
|
||
|
pvt_try_restate(pvt);
|
||
|
}
|
||
|
|
||
|
ast_free(cpvt);
|
||
|
}
|
||
|
|
||
|
#/* */
|
||
|
EXPORT_DEF struct cpvt * pvt_find_cpvt(struct pvt * pvt, int call_idx)
|
||
|
{
|
||
|
struct cpvt * cpvt;
|
||
|
AST_LIST_TRAVERSE(&pvt->chans, cpvt, entry) {
|
||
|
if(call_idx == cpvt->call_idx)
|
||
|
return cpvt;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#/* */
|
||
|
EXPORT_DEF const char * pvt_call_dir(const struct pvt * pvt)
|
||
|
{
|
||
|
static const char * dirs[] = {
|
||
|
"Active",
|
||
|
"Outgoing",
|
||
|
"Incoming",
|
||
|
"Both"
|
||
|
};
|
||
|
|
||
|
int index = 0;
|
||
|
struct cpvt * cpvt;
|
||
|
AST_LIST_TRAVERSE(&pvt->chans, cpvt, entry) {
|
||
|
if(cpvt->dir == CALL_DIR_OUTGOING)
|
||
|
index |= 0x1;
|
||
|
else
|
||
|
index |= 0x2;
|
||
|
}
|
||
|
|
||
|
return dirs[index];
|
||
|
}
|