summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuper User2008-05-18 19:04:35 +0200
committerSuper User2008-05-18 19:04:35 +0200
commit58b134cb12ac8526321da6e270c93b9d0e78a3e0 (patch)
treef8bc959448a6bcd9ce08eae7c84b80872e15a7d8
parentwork on chan_lcr (diff)
downloadlcr-58b134cb12ac8526321da6e270c93b9d0e78a3e0.tar.gz
lcr-58b134cb12ac8526321da6e270c93b9d0e78a3e0.tar.xz
lcr-58b134cb12ac8526321da6e270c93b9d0e78a3e0.zip
lcr work (soon done :)
modified: Makefile modified: bchannel.c modified: chan_lcr.c modified: chan_lcr.h modified: dss1.cpp modified: todo.txt
-rw-r--r--Makefile2
-rw-r--r--bchannel.c69
-rw-r--r--chan_lcr.c422
-rw-r--r--chan_lcr.h8
-rw-r--r--dss1.cpp65
-rw-r--r--todo.txt13
6 files changed, 368 insertions, 211 deletions
diff --git a/Makefile b/Makefile
index 254448c..0f8a0e9 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@
#*****************************************************************************/
WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used
-#WITH-ASTERISK = 42 # comment this out, if you don't require built-in Asterisk channel driver.
+WITH-ASTERISK = 42 # comment this out, if you don't require built-in Asterisk channel driver.
WITH-SOCKET = 42 # compile for socket based mISDN (this options is far unfinished !!!)
# note: check your location and the names of libraries.
diff --git a/bchannel.c b/bchannel.c
index 42831d8..7e2db3b 100644
--- a/bchannel.c
+++ b/bchannel.c
@@ -42,9 +42,6 @@
#define ISDN_PID_L4_B_USER 0x440000ff
#endif
-#define PERROR(arg...) fprintf(stderr, ##arg)
-#define PDEBUG(arg...) while(0)
-
pid_t bchannel_pid;
enum {
@@ -79,11 +76,11 @@ int bchannel_initialize(void)
ret = mISDN_open();
if (ret < 0)
{
- PERROR("cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
+ CERROR("cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
return(-1);
}
bchannel_device = ret;
- PDEBUG("mISDN device opened.\n");
+ CDEBUG("mISDN device opened.\n");
/* create entity for layer 3 TE-mode */
mISDN_write_frame(bchannel_device, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
@@ -91,7 +88,7 @@ int bchannel_initialize(void)
if (ret < (int)mISDN_HEADER_LEN)
{
noentity:
- PERROR("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
+ CERROR("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
return(-1);
}
bchannel_entity = frm->dinfo & 0xffff;
@@ -133,7 +130,7 @@ static void ph_control(unsigned long handle, unsigned long c1, unsigned long c2,
*d++ = c2;
ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
if (!ret)
- PERROR("Failed to send to socket %d\n", handle);
+ CERROR("Failed to send to socket %d\n", handle);
#else
unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
iframe_t *ctrl = (iframe_t *)buffer;
@@ -171,7 +168,7 @@ static void ph_control_block(unsigned long handle, unsigned long c1, void *c2, i
memcpy(d, c2, c2_len);
ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
if (!ret)
- PERROR("Failed to send to socket %d\n", handle);
+ CERROR("Failed to send to socket %d\n", handle);
#else
unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
iframe_t *ctrl = (iframe_t *)buffer;
@@ -206,7 +203,7 @@ int bchannel_create(struct bchannel *bchannel)
if (bchannel->b_sock)
{
- PERROR("Error: Socket already created for handle 0x%x\n", bchannel->handle);
+ CERROR("Error: Socket already created for handle 0x%x\n", bchannel->handle);
return(0);
}
@@ -217,7 +214,7 @@ int bchannel_create(struct bchannel *bchannel)
channel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
if (bchannel->b_sock < 0)
{
- PERROR("Error: Failed to open bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
+ CERROR("Error: Failed to open bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
return(0);
}
@@ -225,7 +222,7 @@ int bchannel_create(struct bchannel *bchannel)
ret = ioctl(bchannel->b_sock, FIONBIO, &on);
if (ret < 0)
{
- PERROR("Error: Failed to set bchannel-socket handle 0x%x into nonblocking IO\n", bchannel->handle);
+ CERROR("Error: Failed to set bchannel-socket handle 0x%x into nonblocking IO\n", bchannel->handle);
close(bchannel->b_sock);
channel->b_sock = -1;
return(0);
@@ -238,7 +235,7 @@ int bchannel_create(struct bchannel *bchannel)
ret = bind(bchannel->b_sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0)
{
- PERROR("Error: Failed to bind bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
+ CERROR("Error: Failed to bind bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
close(bchannel->b_sock);
channel->b_sock = -1;
return(0);
@@ -256,18 +253,18 @@ int bchannel_create(struct bchannel *bchannel)
if (bchannel->b_stid)
{
- PERROR("Error: stack already created for address 0x%lx\n", bchannel->b_stid);
+ CERROR("Error: stack already created for address 0x%lx\n", bchannel->b_stid);
return(0);
}
if (bchannel->b_addr)
{
- PERROR("Error: stack already created for address 0x%lx\n", bchannel->b_addr);
+ CERROR("Error: stack already created for address 0x%lx\n", bchannel->b_addr);
return(0);
}
/* create new layer */
- PDEBUG("creating new layer for stid 0x%lx.\n" , bchannel->handle);
+ CDEBUG("creating new layer for stid 0x%lx.\n" , bchannel->handle);
memset(&li, 0, sizeof(li));
memset(&pid, 0, sizeof(pid));
li.object_id = -1;
@@ -280,7 +277,7 @@ int bchannel_create(struct bchannel *bchannel)
if (ret)
{
failed_new_layer:
- PERROR("mISDN_new_layer() failed to add bchannel for stid 0x%lx.\n", bchannel->handle);
+ CERROR("mISDN_new_layer() failed to add bchannel for stid 0x%lx.\n", bchannel->handle);
goto failed;
}
if (!li.id)
@@ -289,7 +286,7 @@ int bchannel_create(struct bchannel *bchannel)
}
bchannel->b_stid = bchannel->handle;
bchannel->b_addr = li.id;
- PDEBUG("new layer (b_addr=0x%x)\n", bchannel->b_addr);
+ CDEBUG("new layer (b_addr=0x%x)\n", bchannel->b_addr);
/* create new stack */
pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
@@ -301,7 +298,7 @@ int bchannel_create(struct bchannel *bchannel)
if (ret)
{
stack_error:
- PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel stid=0x%lx\n", ret, bchannel->b_stid);
+ CERROR("mISDN_set_stack() failed (ret=%d) to add bchannel stid=0x%lx\n", ret, bchannel->b_stid);
mISDN_write_frame(bchannel_device, buff, bchannel->b_addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
goto failed;
}
@@ -344,7 +341,7 @@ void bchannel_activate(struct bchannel *bchannel, int activate)
act.id = 0;
ret = sendto(bchannel->b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
if (!ret)
- PERROR("Failed to send to socket %d\n", bchannel->b_sock);
+ CERROR("Failed to send to socket %d\n", bchannel->b_sock);
#else
iframe_t act;
@@ -444,7 +441,7 @@ static void bchannel_destroy(struct bchannel *bchannel)
/* remove our stack only if set */
if (bchannel->b_addr)
{
- PDEBUG("free stack (b_addr=0x%x)\n", bchannel->b_addr);
+ CDEBUG("free stack (b_addr=0x%x)\n", bchannel->b_addr);
mISDN_clear_stack(bchannel_device, bchannel->b_stid);
mISDN_write_frame(bchannel_device, buff, bchannel->b_addr | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
bchannel->b_stid = 0;
@@ -470,7 +467,7 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
{
if (len < 4)
{
- PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
+ CERROR("SHORT READ OF PH_CONTROL INDICATION\n");
return;
}
if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
@@ -521,7 +518,7 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
if (!bchannel->b_txdata)
{
/* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
- PDEBUG("PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
+ CDEBUG("PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
return;
}
break;
@@ -539,7 +536,7 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
}
if (prim != PH_DATA_IND && prim != DL_DATA_IND)
{
- PERROR("Bchannel received unknown primitve: 0x%lx\n", prim);
+ CERROR("Bchannel received unknown primitve: 0x%lx\n", prim);
return;
}
/* calls will not process any audio data unless
@@ -549,19 +546,19 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
/* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
if (bchannel->b_rxoff)
{
- PDEBUG("PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
+ CDEBUG("PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
return;
}
if (!bchannel->call)
{
- PDEBUG("PmISDN(%s) ignoring data, because no call associated with bchannel\n", p_name);
+ CDEBUG("PmISDN(%s) ignoring data, because no call associated with bchannel\n", p_name);
return;
}
len = write(bchannel->call->pipe[1], data, len);
if (len < 0)
{
- PDEBUG("PmISDN(%s) broken pipe on bchannel pipe\n", p_name);
+ CDEBUG("PmISDN(%s) broken pipe on bchannel pipe\n", p_name);
return;
}
}
@@ -582,7 +579,7 @@ void bchannel_transmit(struct bchannel *bchannel, unsigned char *data, int len)
frm->id = 0;
ret = sendto(bchannel->b_sock, data, len, 0, NULL, 0);
if (!ret)
- PERROR("Failed to send to socket %d\n", bchannel->b_sock);
+ CERROR("Failed to send to socket %d\n", bchannel->b_sock);
#else
frm->prim = DL_DATA | REQUEST;
frm->addr = bchannel->b_addr | FLG_MSG_DOWN;
@@ -665,7 +662,7 @@ int bchannel_handle(void)
case DL_ESTABLISH_IND:
case PH_ACTIVATE_CONF:
case DL_ESTABLISH_CONF:
- PDEBUG("DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", bchannel->b_sock);
+ CDEBUG("DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", bchannel->b_sock);
bchannel_activated(bchannel);
break;
@@ -673,17 +670,17 @@ int bchannel_handle(void)
case DL_RELEASE_IND:
case PH_DEACTIVATE_CONF:
case DL_RELEASE_CONF:
- PDEBUG("DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", bchannel->b_sock);
+ CDEBUG("DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", bchannel->b_sock);
// bchannel_deactivated(bchannel);
break;
default:
- PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, bchannel->b_sock, msg->len);
+ CERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, bchannel->b_sock, msg->len);
}
} else
{
if (ret < 0 && errno != EWOULDBLOCK)
- PERROR("Read from socket %d failed with return code %d\n", bchannel->b_sock, ret);
+ CERROR("Read from socket %d failed with return code %d\n", bchannel->b_sock, ret);
}
}
bchannel = bchannel->next;
@@ -710,7 +707,7 @@ int bchannel_handle(void)
{
if (errno == EAGAIN)
return(0);
- PERROR("Failed to do mISDN_read()\n");
+ CERROR("Failed to do mISDN_read()\n");
return(0);
}
if (!len)
@@ -741,7 +738,7 @@ int bchannel_handle(void)
}
if (!bchannel)
{
- PERROR("message belongs to no bchannel: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
+ CERROR("message belongs to no bchannel: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
goto out;
}
@@ -765,7 +762,7 @@ int bchannel_handle(void)
case DL_ESTABLISH | INDICATION:
case PH_ACTIVATE | CONFIRM:
case DL_ESTABLISH | CONFIRM:
- PDEBUG( "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
+ CDEBUG( "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
bchannel_activated(bchannel);
break;
@@ -773,12 +770,12 @@ int bchannel_handle(void)
case DL_RELEASE | INDICATION:
case PH_DEACTIVATE | CONFIRM:
case DL_RELEASE | CONFIRM:
- PDEBUG("DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
+ CDEBUG("DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
// bchannel_deactivated(bchannel);
break;
default:
- PERROR("message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
+ CERROR("message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
}
out:
diff --git a/chan_lcr.c b/chan_lcr.c
index f33d917..18cbec7 100644
--- a/chan_lcr.c
+++ b/chan_lcr.c
@@ -79,13 +79,6 @@ If the ref is 0 and the state is CHAN_LCR_STATE_RELEASE, see the proceedure
*/
-u_char flip_bits[256];
-
-#warning TODO: bchannel oeffnen und aktivieren (wer macht das?:)
-#warning reconnect after socket closed, release all calls.
-#warning debug of call handling
-#warning ausloesen beim socket-verlust
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -131,13 +124,16 @@ u_char flip_bits[256];
CHAN_LCR_STATE // state description structure
+u_char flip_bits[256];
+
int lcr_debug=1;
int mISDN_created=1;
char lcr_type[]="lcr";
pthread_t chan_tid;
-ast_mutex_t chan_lock;
+ast_mutex_t chan_lock; /* global lock */
+ast_mutex_t log_lock; /* logging log */
int quit;
int glob_channel = 0;
@@ -152,6 +148,34 @@ struct admin_list {
static struct ast_channel_tech lcr_tech;
/*
+ * logging
+ */
+void chan_lcr_log(int type, struct chan_call *call, struct ast_channel *ast, const char *fmt, ...)
+{
+ char buffer[1024];
+ char call_text[128] = "NULL";
+ char ast_text[128] = "NULL";
+ va_list args;
+
+ ast_mutex_lock(&log_lock);
+
+ va_start(args,fmt);
+ vsnprintf(buffer,sizeof(buffer)-1,fmt,args);
+ buffer[sizeof(buffer)-1]=0;
+ va_end(args);
+
+ if (call)
+ sprintf(call_text, "%ld", call->ref);
+ if (ast)
+ strncpy(ast_text, ast->name, sizeof(ast_text)-1);
+ ast_text[sizeof(ast_text)-1] = '\0';
+
+ ast_log(type, "[call=%s ast=%s] %s", call_text, ast_text, buffer);
+
+ ast_mutex_unlock(&log_lock);
+}
+
+/*
* channel and call instances
*/
struct chan_call *call_first;
@@ -197,24 +221,6 @@ struct chan_call *find_call_handle(unsigned long handle)
}
#endif
-struct chan_call *alloc_call(void)
-{
- struct chan_call **callp = &call_first;
-
- while(*callp)
- callp = &((*callp)->next);
-
- *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
- if (*callp)
- memset(*callp, 0, sizeof(struct chan_call));
- if (pipe((*callp)->pipe) < 0) {
- free_call(*callp);
- return;
- }
- return(*callp);
-}
-
-
void free_call(struct chan_call *call)
{
struct chan_call **temp = &call_first;
@@ -230,25 +236,45 @@ void free_call(struct chan_call *call)
close(call->pipe[1]);
if (call->bchannel)
{
- if (call->bchannel->call)
- call->bchannel->call = NULL;
- else
- warnung
+ if (call->bchannel->call != call)
+ CERROR(call, NULL, "Linked bchannel structure has no link to us.\n");
+ call->bchannel->call = NULL;
}
if (call->bridge_call)
{
- if (call->bridge_call->bridge_call)
- call->bridge_call->bridge_call = NULL;
- else
- warnung
+ if (call->bridge_call->bridge_call != call)
+ CERROR(call, NULL, "Linked call structure has no link to us.\n");
+ call->bridge_call->bridge_call = NULL;
}
+ CDEBUG(call, NULL, "Call instance freed.\n");
free(call);
return;
}
temp = &((*temp)->next);
}
+ CERROR(call, NULL, "Call instance not found in list.\n");
}
+struct chan_call *alloc_call(void)
+{
+ struct chan_call **callp = &call_first;
+
+ while(*callp)
+ callp = &((*callp)->next);
+
+ *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
+ if (*callp)
+ memset(*callp, 0, sizeof(struct chan_call));
+ if (pipe((*callp)->pipe) < 0) {
+ CERROR(*callp, NULL, "Failed to create pipe.\n");
+ free_call(*callp);
+ return(NULL);
+ }
+ CDEBUG(*callp, NULL, "Call instance allocated.\n");
+ return(*callp);
+}
+
+
unsigned short new_bridge_id(void)
{
struct chan_call *call;
@@ -268,28 +294,24 @@ unsigned short new_bridge_id(void)
break;
id++;
}
+ CDEBUG(NULL, NULL, "New bridge ID %d.\n", id);
return(id);
}
/*
- * receive bchannel data
- */
-void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
-{
-}
-
-void rx_dtmf(struct bchannel *bchannel, char tone)
-{
-}
-
-/*
* enque message to LCR
*/
int send_message(int message_type, unsigned long ref, union parameter *param)
{
struct admin_list *admin, **adminp;
+ if (lcr_sock < 0) {
+ CDEBUG(NULL, NULL, "Ignoring message %d, because socket is closed.\n", message_type);
+ return -1;
+ }
+ CDEBUG(NULL, NULL, "Sending message %d to socket.\n", message_type);
+
adminp = &admin_first;
while(*adminp)
adminp = &((*adminp)->next);
@@ -315,6 +337,8 @@ static void send_setup_to_lcr(struct chan_call *call)
if (!call->ast || !call->ref)
return;
+ CDEBUG(call, call->ast, "Sending setup to LCR.\n");
+
/* send setup message to LCR */
memset(&newparam, 0, sizeof(union parameter));
newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;
@@ -381,6 +405,8 @@ static void send_dialque_to_lcr(struct chan_call *call)
if (!call->ast || !call->ref || !call->dialque)
return;
+ CDEBUG(call, call->ast, "Sending dial queue to LCR.\n");
+
/* send setup message to LCR */
memset(&newparam, 0, sizeof(union parameter));
strncpy(newparam.information.id, call->dialque, sizeof(newparam.information.id)-1);
@@ -397,6 +423,7 @@ static void bridge_message_if_bridged(struct chan_call *call, int message_type,
/* check bridge */
if (!call) return;
if (!call->bridge_call) return;
+ CDEBUG(call, NULL, "Sending message due briding.\n");
send_message(message_type, call->bridge_call->ref, param);
}
@@ -405,22 +432,25 @@ static void bridge_message_if_bridged(struct chan_call *call, int message_type,
* if it can match, proceed
* if not, release
*/
-static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int complete)
+static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int complete)
{
int cause;
if (complete)
{
/* if not match */
- if (!ast_canmatch_extension(ast, ast->context, call->dad, 1, call->oad))
+ if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, call->oad))
{
+ CDEBUG(call, ast, "Got 'sending complete', but extension '%s' will not match at context '%s' - releasing.\n", ast->exten, ast->context);
cause = 1;
goto release;
- if (!ast_exists_extension(ast, ast->context, call->dad, 1, call->oad))
+ if (!ast_exists_extension(ast, ast->context, ast->exten, 1, call->oad))
{
+ CDEBUG(call, ast, "Got 'sending complete', but extension '%s' would match at context '%s', if more digits would be dialed - releasing.\n", ast->exten, ast->context);
cause = 28;
goto release;
}
+ CDEBUG(call, ast, "Got 'sending complete', extensions matches.\n");
/* send setup acknowledge to lcr */
memset(&newparam, 0, sizeof(union parameter));
send_message(MESSAGE_PROCEEDING, call->ref, &newparam);
@@ -441,10 +471,13 @@ static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int c
call->state = CHAN_LCR_STATE_IN_DIALING;
/* if match, start pbx */
- if (ast_exists_extension(ast, ast->context, dad, 1, oad))
+ if (ast_exists_extension(ast, ast->context, dad, 1, oad)) {
+ CDEBUG(call, ast, "Extensions matches.\n");
goto start;
+ }
/* if can match */
+ CDEBUG(call, ast, "Extensions may match, if more digits are dialed.\n");
return;
}
@@ -452,6 +485,7 @@ static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int c
cause = 1;
release:
/* release lcr */
+ CDEBUG(call, ast, "Releasing due to extension missmatch.\n");
memset(&newparam, 0, sizeof(union parameter));
newparam.disconnectinfo.cause = cause;
newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@@ -459,13 +493,14 @@ static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int c
call->ref = 0;
/* release asterisk */
ast->hangupcause = call->cause;
- ast_queue_hangup(ast);
/* change to release state */
call->state = CHAN_LCR_STATE_RELEASE;
+ ast_hangup(ast); // call will be destroyed here
return;
start:
/* send setup to asterisk */
+ CDEBUG(call, ast, "Starting call to Asterisk due to matching extension.\n");
ret = ast_pbx_start(ast);
if (ret < 0)
{
@@ -484,11 +519,14 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
struct ast_channel *ast;
union parameter newparam;
+ CDEBUG(call, NULL, "Incomming setup from LCR. (callerid %d, dialing %d)\n", param->setup.callerinfo.id, param->setup.dialinginfo.id);
+
/* create asterisk channel instrance */
ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
if (!ast)
{
/* release */
+ CERROR(call, NULL, "Failed to create Asterisk channel - releasing.\n");
memset(&newparam, 0, sizeof(union parameter));
newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@@ -543,8 +581,7 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
ast->cid.cid_ton = 0;
}
ast->transfercapability = param->setup.capainfo.bearer_capa;
- strcpy(call->dad, param->setup.dialinginfo.id);
- strcpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, configfile->prefix_nat, configfile->prefix_inter));
+ strncpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, configfile->prefix_nat, configfile->prefix_inter), sizeof(call->oad)-1);
/* configure channel */
#warning todo
@@ -568,6 +605,8 @@ static void lcr_in_overlap(struct chan_call *call, int message_type, union param
{
if (!call->ast) return;
+ CDEBUG(call, call->ast, "Incomming setup acknowledge from LCR.\n");
+
/* send pending digits in dialque */
if (call->dialque)
send_dialque_to_lcr(call);
@@ -580,10 +619,12 @@ static void lcr_in_overlap(struct chan_call *call, int message_type, union param
*/
static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
{
+ CDEBUG(call, call->ast, "Incomming proceeding from LCR.\n");
+
/* change state */
call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
/* send event to asterisk */
- if (call->ast)
+ if (call->ast && call->pbx_started)
ast_queue_control(call->ast, AST_CONTROL_PROCEEDING);
}
@@ -592,10 +633,12 @@ static void lcr_in_proceeding(struct chan_call *call, int message_type, union pa
*/
static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
{
+ CDEBUG(call, call->ast, "Incomming alerting from LCR.\n");
+
/* change state */
call->state = CHAN_LCR_STATE_OUT_ALERTING;
/* send event to asterisk */
- if (call->ast)
+ if (call->ast && call->pbx_started)
ast_queue_control(call->ast, AST_CONTROL_RINGING);
}
@@ -604,12 +647,14 @@ static void lcr_in_alerting(struct chan_call *call, int message_type, union para
*/
static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
{
+ CDEBUG(call, call->ast, "Incomming connect (answer) from LCR.\n");
+
/* change state */
call->state = CHAN_LCR_STATE_CONNECT;
/* copy connectinfo */
memcpy(&call->connectinfo, &param->connectinfo, sizeof(struct connect_info));
/* send event to asterisk */
- if (call->ast)
+ if (call->ast && call->pbx_started)
ast_queue_control(call->ast, AST_CONTROL_ANSWER);
}
@@ -621,30 +666,38 @@ static void lcr_in_disconnect(struct chan_call *call, int message_type, union pa
struct ast_channel *ast = call->ast;
union parameter newparam;
+ CDEBUG(call, call->ast, "Incomming disconnect from LCR. (cause=%d)\n", param.disconnectinfo.cause);
+
/* change state */
call->state = CHAN_LCR_STATE_IN_DISCONNECT;
/* save cause */
call->cause = param->disconnectinfo.cause;
call->location = param->disconnectinfo.location;
-per option
-
-wenn setup raus geht, pointer
/* if bridge, forward disconnect and return */
+#ifdef TODO
+ feature flag
if (call->bridge_call)
{
+ CDEBUG(call, call->ast, "Only signal disconnect via bridge.\n");
bridge_message_if_bridged(call, message_type, param);
return;
}
- /* release lcr */
- newparam.disconnectinfo.cause = CAUSE_NORMAL;
- newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- send_message(MESSAGE_RELEASE, call->ref, &newparam);
+#endif
+ /* release lcr with same cause */
+ send_message(MESSAGE_RELEASE, call->ref, param);
call->ref = 0;
- /* release asterisk */
- ast->hangupcause = call->cause;
- ast_queue_hangup(ast);
/* change to release state */
call->state = CHAN_LCR_STATE_RELEASE;
+ /* release asterisk */
+ if (ast)
+ {
+ ast->hangupcause = call->cause;
+ if (call->pbx_started)
+ ast_queue_hangup(ast);
+ else {
+ ast_hangup(ast); // call will be destroyed here
+ }
+ }
}
/*
@@ -654,6 +707,8 @@ static void lcr_in_release(struct chan_call *call, int message_type, union param
{
struct ast_channel *ast = call->ast;
+ CDEBUG(call, call->ast, "Incomming release from LCR. (cause=%d)\n", param.disconnectinfo.cause);
+
/* release ref */
call->ref = 0;
/* change to release state */
@@ -668,7 +723,11 @@ static void lcr_in_release(struct chan_call *call, int message_type, union param
if (ast)
{
ast->hangupcause = call->cause;
- ast_queue_hangup(ast);
+ if (call->pbx_started)
+ ast_queue_hangup(ast);
+ else {
+ ast_hangup(ast); // call will be destroyed here
+ }
} else
{
free_call(call);
@@ -684,11 +743,14 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
struct ast_frame fr;
char *p;
+ CDEBUG(call, call->ast, "Incomming information from LCR. (dialing=%d)\n", param.information.id);
+
if (!call->ast) return;
/* pbx not started */
if (!call->pbx_started)
{
+ CDEBUG(call, call->ast, "Asterisk not started, adding digits to number.\n");
strncat(ast->exten, param->information.id, AST_MAX_EXTENSION-1);
lcr_start_pbx(call, ast, param->information.complete);
return;
@@ -698,6 +760,7 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
p = param->information.id;
if (call->state == CHAN_LCR_STATE_IN_DIALING && *p)
{
+ CDEBUG(call, call->ast, "Asterisk is started, sending DTMF frame.\n");
while (*p)
{
/* send digit to asterisk */
@@ -710,8 +773,10 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
}
}
/* use bridge to forware message not supported by asterisk */
- if (call->state == CHAN_LCR_STATE_CONNECT)
+ if (call->state == CHAN_LCR_STATE_CONNECT) {
+ CDEBUG(call, call->ast, "Call is connected, briding.\n");
bridge_message_if_bridged(call, message_type, param);
+ }
}
/*
@@ -719,6 +784,8 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
*/
static void lcr_in_notify(struct chan_call *call, int message_type, union parameter *param)
{
+ CDEBUG(call, call->ast, "Incomming notify from LCR. (notify=%d)\n", param.notifyinfo.notify);
+
if (!call->ast) return;
/* use bridge to forware message not supported by asterisk */
@@ -730,6 +797,8 @@ static void lcr_in_notify(struct chan_call *call, int message_type, union parame
*/
static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
{
+ CDEBUG(call, call->ast, "Incomming facility from LCR.\n");
+
if (!call->ast) return;
/* use bridge to forware message not supported by asterisk */
@@ -753,16 +822,17 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
switch(param->bchannel.type)
{
case BCHANNEL_ASSIGN:
+ CDEBUG(NULL, NULL "Received BCHANNEL_ASSIGN message. (handle=%08lx)\n", param->bchannel.handle);
if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
{
- fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
+ CERROR(NULL, NULL, "bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
return(-1);
}
/* create bchannel */
bchannel = alloc_bchannel(param->bchannel.handle);
if (!bchannel)
{
- fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
+ CERROR(NULL, NULL, "alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
return(-1);
}
@@ -788,8 +858,10 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
bchannel->call = call;
call->bchannel = bchannel;
#warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
- if (call->bridge_id)
+ if (call->bridge_id) {
+ CDEBUG(call, call->ast, "Join bchannel, because call is already bridged.\n");
bchannel_join(bchannel, call->bridge_id);
+ }
}
if (bchannel_create(bchannel))
bchannel_activate(bchannel, 1);
@@ -801,10 +873,10 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
break;
case BCHANNEL_REMOVE:
+ CDEBUG(NULL, NULL, "Received BCHANNEL_REMOVE message. (handle=%08lx)\n", param->bchannel.handle);
if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
{
- #warning alle fprintf nach ast_log
- fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
+ CERROR(NULL, NULL, "Bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
return(-1);
}
/* unklink from call and destroy bchannel */
@@ -818,7 +890,7 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
break;
default:
- fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
+ CDEBUG(NULL, NULL, "Received unknown bchannel message %d.\n", param->bchannel.type);
}
return(0);
}
@@ -829,9 +901,10 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
if (param->direction)
{
/* new ref from lcr */
+ CDEBUG(NULL, NULL, "Received new ref by LCR, of call from LCR. (ref=%ld)\n", ref);
if (!ref || find_call_ref(ref))
{
- fprintf(stderr, "illegal new ref %ld received\n", ref);
+ CERROR(NULL, NULL, "Illegal new ref %ld received.\n", ref);
return(-1);
}
/* allocate new call instance */
@@ -844,10 +917,12 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
} else
{
/* new ref, as requested from this remote application */
+ CDEBUG(NULL, NULL, "Received new ref by LCR, as requested from chan_lcr. (ref=%ld)\n", ref);
call = find_call_ref(0);
if (!call)
{
/* send release, if ref does not exist */
+ CDEBUG(NULL, NULL, "No call found, that requests a ref.\n");
newparam.disconnectinfo.cause = CAUSE_NORMAL;
newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
send_message(MESSAGE_RELEASE, ref, &newparam);
@@ -883,7 +958,7 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
/* check ref */
if (!ref)
{
- fprintf(stderr, "received message %d without ref\n", message_type);
+ CERROR(NULL, NULL, "Received message %d without ref.\n", message_type);
return(-1);
}
call = find_call_ref(ref);
@@ -955,6 +1030,43 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
return(0);
}
+/*
+ * release all calls (due to broken socket)
+ */
+static void release_all_calls(void)
+{
+ struct chan_call *call;
+
+again:
+ call = call_first;
+ while(call)
+ {
+ /* no ast, so we may directly free call */
+ if (!call->ast) {
+ CDEBUG(call, NULL, "Freeing call, because no Asterisk channel is linked.\n");
+ free_call(call);
+ goto again;
+ }
+ /* already in release process */
+ if (call->state == CHAN_LCR_STATE_RELEASE) {
+ call = call->next;
+ continue;
+ }
+ /* release or queue release */
+ call->ref = 0;
+ call->state = CHAN_LCR_STATE_RELEASE;
+ if (!call->pbx_started)
+ {
+ CDEBUG(call, call->ast, "Releasing call, because no Asterisk channel is not started.\n");
+ ast_hangup(call->ast); // call will be destroyed here
+ goto again;
+ }
+ CDEBUG(call, call->ast, "Queue call release, because Asterisk channel is running.\n");
+ ast_queue_hangup(call->ast);
+ call = call->next;
+ }
+}
+
/* asterisk handler
* warning! not thread safe
@@ -974,29 +1086,28 @@ int handle_socket(void)
len = read(sock, &msg, sizeof(msg));
if (len == 0)
{
- printf("Socket closed\n");
+ CERROR(NULL, NULL, "Socket closed.\n");
return(-1); // socket closed
}
if (len > 0)
{
if (len != sizeof(msg))
{
- fprintf(stderr, "Socket short read (%d)\n", len);
+ CERROR(NULL, NULL, "Socket short read. (len %d)\n", len);
return(-1); // socket error
}
if (msg.message != ADMIN_MESSAGE)
{
- fprintf(stderr, "Socket received illegal message %d\n", msg.message);
+ CERROR(NULL, NULL, "Socket received illegal message %d.\n", msg.message);
return(-1); // socket error
}
receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
- printf("message received %d\n", msg.u.msg.type);
work = 1;
} else
{
if (errno != EWOULDBLOCK)
{
- fprintf(stderr, "Socket error %d\n", errno);
+ CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
return(-1);
}
}
@@ -1008,14 +1119,14 @@ int handle_socket(void)
len = write(sock, &admin->msg, sizeof(msg));
if (len == 0)
{
- printf("Socket closed\n");
+ CERROR(NULL, NULL, "Socket closed.\n");
return(-1); // socket closed
}
if (len > 0)
{
if (len != sizeof(msg))
{
- fprintf(stderr, "Socket short write (%d)\n", len);
+ CERROR(NULL, NULL, "Socket short write. (len %d)\n", len);
return(-1); // socket error
}
/* free head */
@@ -1027,7 +1138,7 @@ int handle_socket(void)
{
if (errno != EWOULDBLOCK)
{
- fprintf(stderr, "Socket error %d\n", errno);
+ CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
return(-1);
}
}
@@ -1051,7 +1162,7 @@ int open_socket(void)
/* open socket */
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
{
- ast_log(LOG_ERROR, "Failed to create socket.\n");
+ CERROR(NULL, NULL, "Failed to create socket.\n");
return(sock);
}
@@ -1064,7 +1175,7 @@ int open_socket(void)
if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
{
close(sock);
- ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
+ CERROR(NULL, NULL, "Failed to connect to socket '%s'. Is LCR running?\n", sock_address.sun_path);
return(conn);
}
@@ -1072,7 +1183,7 @@ int open_socket(void)
if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
{
close(sock);
- ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
+ CERROR(NULL, NULL, "Failed to set socket into non-blocking IO.\n");
return(ret);
}
@@ -1095,32 +1206,58 @@ static void *chan_thread(void *arg)
{
int work;
int ret;
+ union parameter param;
+ time_t retry = 0, now;
+
+ bchannel_pid = getpid();
+
+ memset(&param, 0, sizeof(union parameter));
+ if (lcr_sock > 0)
+ time(&retry);
ast_mutex_lock(&chan_lock);
- while(!quit)
- {
+ while(!quit) {
work = 0;
- /* handle socket */
- ret = handle_socket();
- if (ret < 0)
- break;
- if (ret)
- work = 1;
+ if (lcr_sock > 0) {
+ /* handle socket */
+ ret = handle_socket();
+ if (ret < 0) {
+ CERROR(NULL, NULL, "Handling of socket failed - closing for some seconds.\n");
+ close_socket(lcr_sock);
+ lcr_sock = -1;
+ release_all_calls();
+ time(&retry);
+ }
+ if (ret)
+ work = 1;
+ } else {
+ time(&now);
+ if (retry && now-retry > 5) {
+ CERROR(NULL, NULL, "Retry to open socket.\n");
+ retry = 0;
+ if (!(lcr_sock = open_socket())) {
+ time(&retry);
+ }
+ work = 1;
+ }
+
+ }
/* handle mISDN */
ret = bchannel_handle();
if (ret)
work = 1;
- if (!work)
- {
+ if (!work) {
ast_mutex_unlock(&chan_lock);
usleep(30000);
ast_mutex_lock(&chan_lock);
}
}
+
+ CERROR(NULL, NULL, "Thread exit.\n");
ast_mutex_unlock(&chan_lock);
@@ -1138,6 +1275,15 @@ static struct ast_channel *lcr_request(const char *type, int format, void *data,
ast_mutex_lock(&chan_lock);
+ CDEBUG(NULL, NULL, "Received request from Asterisk.\n");
+
+ /* if socket is closed */
+ if (lcr_sock < 0)
+ {
+ CERROR(NULL, NULL, "Rejecting call from Asterisk, because LCR not running.\n");
+ return NULL;
+ }
+
/* create call instance */
call = alloc_call();
if (!call)
@@ -1149,6 +1295,7 @@ static struct ast_channel *lcr_request(const char *type, int format, void *data,
ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
if (!ast)
{
+ CERROR(NULL, NULL, "Failed to create Asterisk channel.\n");
free_call(call);
/* failed to create instance */
return NULL;
@@ -1189,26 +1336,19 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
ast_mutex_lock(&chan_lock);
call = ast->tech_pvt;
if (!call) {
+ CERROR(NULL, ast, "Received call from Asterisk, but no call instance exists.\n");
ast_mutex_unlock(&chan_lock);
return -1;
}
+ CDEBUG(call, ast, "Received call from Asterisk.\n");
-#warning hier muss noch
-#if 0
- ast_copy_string(buf, dest, sizeof(buf)-1);
- p=buf;
- port_str=strsep(&p, "/");
- dad=strsep(&p, "/");
-#endif
+ call->pbx_started = 1;
/* send setup message, if we already have a callref */
if (call->ref)
send_setup_to_lcr(call);
-// if (lcr_debug)
- // ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
-
ast_mutex_unlock(&chan_lock);
return 0;
}
@@ -1226,13 +1366,17 @@ static int lcr_digit(struct ast_channel *ast, char digit)
ast_mutex_lock(&chan_lock);
call = ast->tech_pvt;
if (!call) {
+ CERROR(NULL, ast, "Received digit from Asterisk, but no call instance exists.\n");
ast_mutex_unlock(&chan_lock);
return -1;
}
+ CDEBUG(call, ast, "Received digit Asterisk.\n");
+
/* send information or queue them */
if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
{
+ CDEBUG(call, ast, "Sending digit to LCR, because we are in dialing state.\n");
memset(&newparam, 0, sizeof(union parameter));
newparam.information.id[0] = digit;
newparam.information.id[1] = '\0';
@@ -1241,6 +1385,7 @@ static int lcr_digit(struct ast_channel *ast, char digit)
if (!call->ref
&& (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
{
+ CDEBUG(call, ast, "Queue digits, because we are in setup/dialing state and have no ref yet.\n");
*buf = digit;
strncat(call->dialque, buf, strlen(call->dialque)-1);
}
@@ -1258,10 +1403,13 @@ static int lcr_answer(struct ast_channel *ast)
ast_mutex_lock(&chan_lock);
call = ast->tech_pvt;
if (!call) {
+ CERROR(NULL, ast, "Received answer from Asterisk, but no call instance exists.\n");
ast_mutex_unlock(&chan_lock);
return -1;
}
+ CDEBUG(call, ast, "Received answer from Asterisk.\n");
+
/* copy connectinfo, if bridged */
if (call->bridge_call)
memcpy(&call->connectinfo, &call->bridge_call->connectinfo, sizeof(struct connect_info));
@@ -1280,27 +1428,38 @@ static int lcr_hangup(struct ast_channel *ast)
{
union parameter newparam;
struct chan_call *call;
+ pthread_t tid = pthread_self();
- ast_mutex_lock(&chan_lock);
+ if (!pthread_equal(tid, call_tid))
+ ast_mutex_lock(&chan_lock);
call = ast->tech_pvt;
if (!call) {
- ast_mutex_unlock(&chan_lock);
+ CERROR(NULL, ast, "Received hangup from Asterisk, but no call instance exists.\n");
+ if (!pthread_equal(tid, call_tid))
+ ast_mutex_unlock(&chan_lock);
return -1;
}
+ if (!pthread_equal(tid, call_tid))
+ CDEBUG(call, ast, "Received hangup from Asterisk thread.\n");
+ else
+ CDEBUG(call, ast, "Received hangup from LCR thread.\n");
+
/* disconnect asterisk, maybe not required */
ast->tech_pvt = NULL;
ast->fds[0] = -1;
if (call->ref)
{
/* release */
+ CDEBUG(call, ast, "Releasing ref and freeing call instance.\n");
memset(&newparam, 0, sizeof(union parameter));
newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
send_message(MESSAGE_RELEASE, call->ref, &newparam);
/* remove call */
free_call(call);
- ast_mutex_unlock(&chan_lock);
+ if (!pthread_equal(tid, call_tid))
+ ast_mutex_unlock(&chan_lock);
return 0;
} else
{
@@ -1308,14 +1467,17 @@ static int lcr_hangup(struct ast_channel *ast)
if (call->state == CHAN_LCR_STATE_RELEASE)
{
/* we get the response to our release */
+ CDEBUG(call, ast, "Freeing call instance, because we have no ref AND we are requesting no ref.\n");
free_call(call);
} else
{
/* during prepare, we change to release state */
+ CDEBUG(call, ast, "We must wait until we received our ref, until we can free call instance.\n");
call->state = CHAN_LCR_STATE_RELEASE;
}
}
- ast_mutex_unlock(&chan_lock);
+ if (!pthread_equal(tid, call_tid))
+ ast_mutex_unlock(&chan_lock);
return 0;
}
@@ -1367,7 +1529,9 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
}
call->read_fr.frametype = AST_FRAME_SPEECH;
-#warning todo
+#ifdef TODO
+ format aus config
+#endif
call->read_fr.subtype = AST_FORMAT_ALAW;
call->read_fr.datalen = len;
call->read_fr.samples = len;
@@ -1387,12 +1551,14 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
ast_mutex_lock(&chan_lock);
call = ast->tech_pvt;
if (!call) {
+ CERROR(NULL, ast, "Received indicate from Asterisk, but no call instance exists.\n");
ast_mutex_unlock(&chan_lock);
return -1;
}
switch (cond) {
case AST_CONTROL_BUSY:
+ CDEBUG(call, ast, "Received indicate AST_CONTROL_BUSY from Asterisk.\n");
/* send message to lcr */
memset(&newparam, 0, sizeof(union parameter));
newparam.disconnectinfo.cause = 17;
@@ -1404,10 +1570,12 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
ast_mutex_unlock(&chan_lock);
return 0;
case AST_CONTROL_CONGESTION:
+ CDEBUG(call, ast, "Received indicate AST_CONTROL_CONGESTION from Asterisk.\n");
/* return */
ast_mutex_unlock(&chan_lock);
return -1;
case AST_CONTROL_RINGING:
+ CDEBUG(call, ast, "Received indicate AST_CONTROL_RINGING from Asterisk.\n");
/* send message to lcr */
memset(&newparam, 0, sizeof(union parameter));
send_message(MESSAGE_ALERTING, call->ref, &newparam);
@@ -1425,12 +1593,14 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
res = -1;
break;
case AST_CONTROL_HOLD:
+ CDEBUG(call, ast, "Received indicate AST_CONTROL_HOLD from Asterisk.\n");
/* send message to lcr */
memset(&newparam, 0, sizeof(union parameter));
newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
send_message(MESSAGE_NOTIFY, call->ref, &newparam);
break;
case AST_CONTROL_UNHOLD:
+ CDEBUG(call, ast, "Received indicate AST_CONTROL_UNHOLD from Asterisk.\n");
/* send message to lcr */
memset(&newparam, 0, sizeof(union parameter));
newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
@@ -1438,7 +1608,7 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
break;
default:
- ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, ast->name);
+ CERROR(call, ast, "Received indicate from Asterisk with unknown condition %d.\n", cond);
/* return */
ast_mutex_unlock(&chan_lock);
return -1;
@@ -1463,7 +1633,9 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
int to = -1;
struct ast_frame *f;
int bridge_id;
-
+
+ CDEBUG(NULL, ast, "Received briding request from Asterisk.\n");
+
/* join via dsp (if the channels are currently open) */
ast_mutex_lock(&chan_lock);
bridge_id = new_bridge_id();
@@ -1489,7 +1661,7 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
who = ast_waitfor_n(carr, 2, &to);
if (!who) {
- ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
+ CDEBUG(NULL, ast, "Empty read on bridge, breaking out.\n");
break;
}
f = ast_read(who);
@@ -1524,6 +1696,8 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
}
+ CDEBUG(NULL, ast, "Releasing bride.\n");
+
/* split channels */
ast_mutex_lock(&chan_lock);
call1 = ast1->tech_pvt;
@@ -1554,7 +1728,9 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
static struct ast_channel_tech lcr_tech = {
.type=lcr_type,
.description="Channel driver for connecting to Linux-Call-Router",
-#warning todo
+#ifdef TODO
+ law from config
+#endif
.capabilities=AST_FORMAT_ALAW,
.requester=lcr_request,
.send_digit_begin=lcr_digit,
@@ -1671,22 +1847,21 @@ int load_module(void)
|| = (i<<7) | ((i&2)<<5) | ((i&4)<<3) | ((i&8)<<1);
ast_mutex_init(&chan_lock);
+ ast_mutex_init(&log_lock);
if (!(lcr_sock = open_socket())) {
- ast_log(LOG_ERROR, "Unable to connect\n");
- lcr_sock = -1;
/* continue with closed socket */
}
if (!bchannel_initialize()) {
- ast_log(LOG_ERROR, "Unable to open mISDN device\n");
+ CERROR(NULL, NULL, "Unable to open mISDN device\n");
close_socket(lcr_sock);
return -1;
}
mISDN_created = 1;
if (ast_channel_register(&lcr_tech)) {
- ast_log(LOG_ERROR, "Unable to register channel class\n");
+ CERROR(NULL, NULL, "Unable to register channel class\n");
bchannel_deinitialize();
close_socket(lcr_sock);
return -1;
@@ -1721,12 +1896,11 @@ int load_module(void)
lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
- chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
=======
//lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
#endif
- quit = 1;
+ quit = 0;
if ((pthread_create(&chan_tid, NULL, chan_thread, NULL)<0))
{
/* failed to create thread */
@@ -1741,7 +1915,7 @@ int load_module(void)
int unload_module(void)
{
/* First, take us out of the channel loop */
- ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
+ CDEBUG(NULL, NULL, "-- Unregistering mISDN Channel Driver --\n");
quit = 1;
pthread_join(chan_tid, NULL);
@@ -1767,7 +1941,8 @@ static int reload_module(void)
return 0;
}
-
+#ifdef TODO
+mutex init fehlt noch
ast_mutex_t usecnt_lock;
int usecnt;
@@ -1779,6 +1954,7 @@ int usecount(void)
ast_mutex_unlock(&usecnt_lock);
return res;
}
+#endif
char *desc="Channel driver for lcr";
diff --git a/chan_lcr.h b/chan_lcr.h
index 87a493f..2388800 100644
--- a/chan_lcr.h
+++ b/chan_lcr.h
@@ -16,6 +16,8 @@ struct chan_call {
int state; /* current call state CHAN_LCR_STATE */
unsigned long ref; /* callref for this channel */
void *ast; /* current asterisk channel */
+ int pbx_started;
+ /* indicates if pbx que is available */
struct bchannel *bchannel;
/* reference to bchannel, if set */
int cause, location;
@@ -28,6 +30,8 @@ struct chan_call {
/* current ID or 0 */
struct chan_call *bridge_call;
/* remote instance or NULL */
+ int pipe[2];
+ /* pipe for receive data */
};
enum {
@@ -82,3 +86,7 @@ enum {
};
+#define CERROR(call, ast, arg...) chan_lcr_log(LOG_ERROR, call, ast, ##arg)
+#define CDEBUG(call, ast, arg...) chan_lcr_log(LOG_DEBUG, call, ast, ##arg)
+void chan_lcr_log(int type, struct chan_call *call, struct ast_channel *ast, const char *fmt, ...);
+
diff --git a/dss1.cpp b/dss1.cpp
index 2df2645..d99954b 100644
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -1319,8 +1319,6 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)((unsigned long)data+headerlen), &location, &cause);
#endif
end_trace();
- if (location == LOCATION_PRIVATE_LOCAL)
- location = LOCATION_PRIVATE_REMOTE;
if (cause < 0)
cause = 16;
@@ -1343,9 +1341,9 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
#endif
l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_REQ, DIRECTION_OUT);
#ifdef SOCKET_MISDN
- enc_ie_cause(l3m, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16); /* normal */
+ enc_ie_cause(l3m, location, cause); /* normal */
#else
- enc_ie_cause(&release->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16); /* normal */
+ enc_ie_cause(&release->CAUSE, dmsg, location, cause); /* normal */
#endif
add_trace("reason", NULL, "no remote patterns");
end_trace();
@@ -1356,6 +1354,8 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
#endif
/* sending release to endpoint */
+ if (location == LOCATION_PRIVATE_LOCAL)
+ location = LOCATION_PRIVATE_REMOTE;
while(p_epointlist)
{
message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
@@ -1371,6 +1371,8 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
}
/* sending disconnect to active endpoint and release to inactive endpoints */
+ if (location == LOCATION_PRIVATE_LOCAL)
+ location = LOCATION_PRIVATE_REMOTE;
if (ACTIVE_EPOINT(p_epointlist))
{
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DISCONNECT);
@@ -1446,50 +1448,36 @@ void Pdss1::release_ind(unsigned long prim, unsigned long dinfo, void *data)
dec_ie_cause(release->CAUSE, (Q931_info_t *)((unsigned long)data+headerlen), &location, &cause);
#endif
end_trace();
- if (location == LOCATION_PRIVATE_LOCAL)
- location = LOCATION_PRIVATE_REMOTE;
if (cause < 0)
cause = 16;
- /* sending release to endpoint */
- while(p_epointlist)
- {
- message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = cause;
- message->param.disconnectinfo.location = location;
- message_put(message);
- /* remove epoint */
- free_epointlist(p_epointlist);
- }
-
+#ifndef SOCKET_MISDN
/* only in NT mode we must send release_complete, if we got a release confirm */
-#ifdef SOCKET_MISDN
- if (cmd == MT_RELEASE)
-#else
if (prim == (CC_RELEASE | CONFIRM))
-#endif
{
/* sending release complete */
-#ifdef SOCKET_MISDN
- l3m = create_l3msg();
-#else
RELEASE_COMPLETE_t *release_complete;
dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, dinfo, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode);
release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen);
-#endif
l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_COMPLETE_REQ, DIRECTION_OUT);
-#ifdef SOCKET_MISDN
- enc_ie_cause(l3m, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16);
-#else
- enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16);
-#endif
+ enc_ie_cause(&release_complete->CAUSE, dmsg, location, cause);
end_trace();
-#ifdef SOCKET_MISDN
- p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_RELEASE_COMPLETE, p_m_d_l3id, l3m);
-#else
msg_queue_tail(&p_m_mISDNport->downqueue, dmsg);
+ }
#endif
+
+ /* sending release to endpoint */
+ if (location == LOCATION_PRIVATE_LOCAL)
+ location = LOCATION_PRIVATE_REMOTE;
+ while(p_epointlist)
+ {
+ message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+ message->param.disconnectinfo.cause = cause;
+ message->param.disconnectinfo.location = location;
+ message_put(message);
+ /* remove epoint */
+ free_epointlist(p_epointlist);
}
new_state(PORT_STATE_RELEASE);
@@ -3577,8 +3565,7 @@ if (/* ||*/ p_state==PORT_STATE_OUT_SETUP)
while(p_epointlist)
{
message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 16;
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+ memcpy(&message->param, param, sizeof(union parameter));
message_put(message);
/* remove epoint */
free_epointlist(p_epointlist);
@@ -3593,9 +3580,9 @@ if (/* ||*/ p_state==PORT_STATE_OUT_SETUP)
l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_COMPLETE_REQ, DIRECTION_OUT);
/* send cause */
#ifdef SOCKET_MISDN
- enc_ie_cause(l3m, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
+ enc_ie_cause(l3m, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
#else
- enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
+ enc_ie_cause(&release_complete->CAUSE, dmsg, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
#endif
end_trace();
#ifdef SOCKET_MISDN
@@ -3664,9 +3651,9 @@ if (/* ||*/ p_state==PORT_STATE_OUT_SETUP)
#endif
/* send cause */
#ifdef SOCKET_MISDN
- enc_ie_cause(l3m, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
+ enc_ie_cause(l3m, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
#else
- enc_ie_cause(&disconnect->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
+ enc_ie_cause(&disconnect->CAUSE, dmsg, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
#endif
/* send display */
if (param->disconnectinfo.display[0])
diff --git a/todo.txt b/todo.txt
index 2ebe280..b3e5041 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,19 +1,8 @@
-socket-test:
-
-- testswitches und karte einbauen
-- call-aufbau ohne bchannel
-- call-aufbau mit bchannel
-- dsp
-- hfc-multi
-- call nach extern
-- l1oip
-
chan_lcr:
- das cli
-- bchannel handling
-- config gile
+- config file
- einbau von b-channel-features