work
[lcr.git] / chan_lcr.c
index 382025b..2cf2ae6 100644 (file)
@@ -83,6 +83,41 @@ locking asterisk process and handler
 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>
@@ -135,6 +170,11 @@ CHAN_LCR_STATE // state description structure
 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;
 
@@ -744,13 +784,14 @@ void close_socket(int sock)
 }
 
 
-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;
 
@@ -767,8 +808,16 @@ void lcr_thread(void)
                        work = 1;
                
                if (!work)
+               {
+                       pthread_mutex_unlock(&chan_lock);
                        usleep(30000);
+                       pthread_mutex_lock(&chan_lock);
+               }
        }
+       
+       pthread_mutex_unlock(&chan_lock);
+
+       return NULL;
 }
 
 /*
@@ -788,6 +837,47 @@ static void send_setup_to_lcr(struct chan_call *call)
        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
@@ -810,6 +900,8 @@ static void send_dialing_to_lcr(struct chan_call *call)
  */
 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)
@@ -834,6 +926,8 @@ static struct ast_channel *lcr_request(const char *type, int format, void *data,
        send_message(MESSAGE_NEWREF, 0, &newparam);
        /* set state */
        call->state = CHAN_LCR_STATE_OUT_PREPARE;
+
+       pthread_mutex_unlock(&chan_lock);
 }
 
 /*
@@ -841,13 +935,14 @@ static struct ast_channel *lcr_request(const char *type, int format, void *data,
  */
 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;
@@ -861,7 +956,9 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
         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; 
 }
 
@@ -869,10 +966,14 @@ static int lcr_digit(struct ast_channel *ast, char digit)
 {
        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)
        {
@@ -888,11 +989,18 @@ static int lcr_digit(struct ast_channel *ast, char digit)
 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;
 }
 
@@ -900,9 +1008,13 @@ static int lcr_hangup(struct ast_channel *ast)
 {
         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));
@@ -911,7 +1023,8 @@ static int lcr_hangup(struct ast_channel *ast)
                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 */
@@ -925,29 +1038,42 @@ static int lcr_hangup(struct ast_channel *ast)
                        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:
@@ -964,14 +1090,16 @@ static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_
 
                 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,
@@ -988,6 +1116,34 @@ static struct ast_channel_tech lcr_tech = {
        .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
  */
@@ -1078,6 +1234,8 @@ int load_module(void)
 
 //     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;
@@ -1086,12 +1244,15 @@ int load_module(void)
 
        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;
        }
  
@@ -1129,6 +1290,15 @@ int load_module(void)
        //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;
 }
 
@@ -1136,7 +1306,9 @@ int unload_module(void)
 {
        /* 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);