reconnect after socket closed, release all calls.
debug of call handling
denke an alle info-elements in jeder message (from asterisk & from lcr)
+ausloesen beim socket-verlust
+
+bei "ast_channel_alloc" kannste die Callerid und den type usw. setzten.
+da kannste auch die calledPartyNum setzen. Um asterisk ein Setup zu schicken rufst du einfach "ast_pbx_start( channel ) " auf. Die ganzen queue baren indications und Controls findest du in "include/asterisk/frame.h"
+
+Also zusammenfassend:
+
+Messages die zum Asterisk gehen:
+
+SETUP - > ast_pbx_start(ast)
+ CONNECT -> ast_queue_control(ast,
+ AST_CONTROL_ANSWER);
+PROCEEDING -> ast_queue_control(ast,
+ AST_CONTROL_PROCEEDING);
+ALERTING -> ast_queue_control(ast,
+ AST_CONTROL_RINGING);
+DISCONNECT -> ast_queue_hangup(ast);
+
+Messages die vom Asterisk kommen:
+
+lcr_request -> NEWREF
+lcr_call -> SETUP
+lcr_answer -> CONNECT
+lcr_hangup -> RELEASE_(complete)
+ lcr_indicate(AST_CONTROL_RINGING) -> ALERTING
+ lcr_indicate(AST_CONTROL_PROCEEDING) -> PROCEEDING
+ lcr_indicate(AST_CONTROL_PROGRESS) -> PROGRESS
+ lcr_indicate(AST_CONTROL_BUSY) -> DISCONNECT ( cause=17 )
+
+
+
+
+
+
+
#include <stdio.h>
int lcr_debug=1;
int mISDN_created=1;
+char lcr_type[]="LCR";
+
+pthread_t chan_tid;
+pthread_mutex_t chan_lock;
+int quit;
int lcr_sock = -1;
}
-hander thread muss noch
socket muss per timer fuer das öffnen checken
-void lcr_thread(void)
+static void *chan_thread(void *arg)
{
int work;
- while(42)
+ pthread_mutex_lock(&chan_lock);
+
+ while(!quit)
{
work = 0;
work = 1;
if (!work)
+ {
+ pthread_mutex_unlock(&chan_lock);
usleep(30000);
+ pthread_mutex_lock(&chan_lock);
+ }
}
+
+ pthread_mutex_unlock(&chan_lock);
+
+ return NULL;
}
/*
call->state = CHAN_LCR_STATE_OUT_SETUP;
}
+#if 0
+CHRISTIAN: das war ein konflikt beim pullen
+siehe anderes lcr_request();
+bedenke: das ast_log muss noch üeberall eingepflegt werden
+
+static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
+{
+ struct chan_call *call=alloc_call();
+
+ if (call) {
+#warning hier muss jetzt wohl eine Ref angefordert werden!
+ ast=lcr_ast_new(call, ext, NULL, 0 );
+
+ if (ast) {
+ call->ast=ast;
+ } else {
+ ast_log(LOG_WARNING, "Could not create new Asterisk Channel\n");
+ free_call(call);
+ }
+ } else {
+ ast_log(LOG_WARNING, "Could not create new Lcr Call Handle\n");
+ }
+
+ return ast;
+}
+
+ struct ast_channel *ast=NULL;
+
+ char buf[128];
+ char *port_str, *ext, *p;
+ int port;
+
+ ast_copy_string(buf, data, sizeof(buf)-1);
+ p=buf;
+ port_str=strsep(&p, "/");
+ ext=strsep(&p, "/");
+ ast_verbose("portstr:%s ext:%s\n",port_str, ext);
+
+ sprintf(buf,"%s/%s",lcr_type,(char*)data);
+#endif
+
/*
* send dialing info to LCR
* this function is called, when setup acknowledge is received and dialing
*/
static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
{
+ pthread_mutex_lock(&chan_lock);
+
/* create call instance */
call = alloc_call();
if (!call)
send_message(MESSAGE_NEWREF, 0, &newparam);
/* set state */
call->state = CHAN_LCR_STATE_OUT_PREPARE;
+
+ pthread_mutex_unlock(&chan_lock);
}
/*
*/
static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
{
- struct lcr_pvt *lcr=ast->tech_pvt;
-
- if (!lcr) return -1;
-
+ struct chan_call *call=ast->tech_pvt;
char buf[128];
char *port_str, *dad, *p;
+ if (!call) return -1;
+
+ pthread_mutex_lock(&chan_lock);
+
hier muss noch
ast_copy_string(buf, dest, sizeof(buf)-1);
p=buf;
if (lcr_debug)
ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
-
+#warning hier müssen wi eine der geholten REFs nehmen und ein SETUP schicken, die INFOS zum SETUP stehen im Ast pointer drin, bzw. werden hier übergeben.
+
+ pthread_mutex_unlock(&chan_lock);
return 0;
}
{
char buf[]="x";
+ if (!call) return -1;
+
/* only pass IA5 number space */
if (digit > 126 || digit < 32)
return 0;
+ pthread_mutex_lock(&chan_lock);
+
/* send information or queue them */
if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
{
digits kommen, koennen aber nicht verwendet werden.
sollen wir sie als info senden (im connect zb.)
}
+
+ pthread_mutex_unlock(&chan_lock);
+
+ return(0);
}
static int lcr_answer(struct ast_channel *c)
{
- struct lcr_pvt *lcr=c->tech_pvt;
+ struct chan_call *call=c->tech_pvt;
+ if (!call) return -1;
+ pthread_mutex_lock(&chan_lock);
+ pthread_mutex_unlock(&chan_lock);
return 0;
}
{
struct chan_call *call = ast->tech_pvt;
+ if (!call)
+ return 0;
+
+ pthread_mutex_lock(&chan_lock);
/* disconnect asterisk, maybe not required */
ast->tech_pvt = NULL;
- if (ref)
+ if (call->ref)
{
/* release */
memset(&newparam, 0, sizeof(union parameter));
send_message(MESSAGE_RELEASE, call->ref, &newparam);
/* remove call */
free_call(call);
- return;
+ pthread_mutex_unlock(&chan_lock);
+ return 0;
} else
{
/* ref is not set, due to prepare setup or release */
call->state = CHAN_LCR_STATE_RELEASE;
}
}
+ pthread_mutex_unlock(&chan_lock);
+ return 0;
}
static int lcr_write(struct ast_channel *c, struct ast_frame *f)
{
- struct lcr_pvt *lcrm= c->tech_pvt;
+ struct chan_call *call= c->tech_pvt;
+ if (!call) return 0;
+ pthread_mutex_lock(&chan_lock);
+ pthread_mutex_unlock(&chan_lock);
}
static struct ast_frame *lcr_read(struct ast_channel *c)
{
- struct lcr_pvt *lcr = c->tech_pvt;
+ struct chan_call *call = c->tech_pvt;
+ if (!call) return 0;
+ pthread_mutex_lock(&chan_lock);
+ pthread_mutex_unlock(&chan_lock);
}
static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
{
int res = -1;
+ if (!call) return -1;
+
+ pthread_mutex_lock(&chan_lock);
switch (cond) {
case AST_CONTROL_BUSY:
case AST_CONTROL_CONGESTION:
case AST_CONTROL_RINGING:
+ pthread_mutex_unlock(&chan_lock);
return -1;
case -1:
+ pthread_mutex_unlock(&chan_lock);
return 0;
case AST_CONTROL_VIDUPDATE:
default:
ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
+ pthread_mutex_unlock(&chan_lock);
return -1;
}
+ pthread_mutex_unlock(&chan_lock);
return 0;
}
static struct ast_channel_tech lcr_tech = {
- .type="lcr",
+ .type=lcr_type,
.description="Channel driver for connecting to Linux-Call-Router",
.capabilities=AST_FORMAT_ALAW,
.requester=lcr_request,
.properties=0
};
+#warning das muss mal aus der config datei gelesen werden:
+char lcr_context[]="from-lcr";
+
+static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref)
+{
+ struct ast_channel *tmp;
+ char *cid_name = 0, *cid_num = 0;
+
+
+ if (callerid)
+ ast_callerid_parse(callerid, &cid_name, &cid_num);
+
+ tmp = ast_channel_alloc(1, AST_STATE_RESERVED, cid_num, cid_name, "", exten, "", 0, "%s/%d", lcr_type, ref);
+
+ if (tmp) {
+ tmp->tech = &lcr_tech;
+ tmp->writeformat = AST_FORMAT_ALAW;
+ tmp->readformat = AST_FORMAT_ALAW;
+
+ ast_copy_string(tmp->context, lcr_context, AST_MAX_CONTEXT);
+
+ }
+
+ return tmp;
+}
+
+
+
/*
* cli
*/
// lcr_cfg_update_ptp();
+ pthread_mutex_init(&chan_lock, NULL);
+
if (!(lcr_sock = open_socket())) {
ast_log(LOG_ERROR, "Unable to connect\n");
lcr_sock = -1;
if (!bchannel_initialize()) {
ast_log(LOG_ERROR, "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");
+ bchannel_deinitialize();
+ close_socket(lcr_sock);
return -1;
}
//lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
#endif
+ quit = 1;
+ if ((pthread_create(&chan_tid, NULL, chan_thread, arg)<0))
+ {
+ failed to create thread
+ bchannel_deinitialize();
+ close_socket(lcr_sock);
+ ast_channel_unregister(&lcr_tech);
+ return -1;
+ }
return 0;
}
{
/* First, take us out of the channel loop */
ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
-
+
+ quit = 1;
+ pthread_join(chan_tid, NULL);
ast_channel_unregister(&lcr_tech);