creation and termination of thread
[lcr.git] / chan_lcr.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** Asterisk socket client                                                    **
9 **                                                                           **
10 \*****************************************************************************/
11
12 /*
13
14 Registering to LCR:
15
16 To connect, open an LCR socket and send a MESSAGE_HELLO to socket with
17 the application name. This name is unique an can be used for routing calls.
18 Now the channel driver is linked to LCR and can receive and make calls.
19
20
21 Call is initiated by LCR:
22
23 If a call is received from LCR, a MESSAGE_NEWREF is received first.
24 A new chan_call instance is created. The call reference (ref) is given by
25 MESSAGE_NEWREF. The state is CHAN_LCR_STATE_IN_PREPARE.
26 After receiving MESSAGE_SETUP from LCR, the ast_channel instance is created
27 using ast_channel_alloc(1).  The setup information is given to asterisk.
28 The new Asterisk instance pointer (ast) is stored to chan_call structure.
29 The state changes to CHAN_LCR_STATE_IN_SETUP.
30
31
32 Call is initiated by Asterisk:
33
34 If a call is reveiced from Asterisk, a new chan_call instance is created.
35 The new Asterisk instance pointer (ast) is stored to chan_call structure.
36 A MESSASGE_NEWREF is sent to LCR requesting a new call reference (ref).
37 The current call ref is set to 0, the state is CHAN_LCR_STATE_OUT_PREPARE.
38 Further dialing information is queued.
39 After the new callref is received by special MESSAGE_NEWREF reply, new ref
40 is stored in the chan_call structure. 
41 The setup information is sent to LCR using MESSAGE_SETUP.
42 The state changes to CHAN_LCR_STATE_OUT_SETUP.
43
44
45 Call is in process:
46
47 During call process, messages are received and sent.
48 The state changes accordingly.
49 Any message is allowed to be sent to LCR at any time except MESSAGE_RELEASE.
50 If a MESSAGE_OVERLAP is received, further dialing is required.
51 Queued dialing information, if any, is sent to LCR using MESSAGE_DIALING.
52 In this case, the state changes to CHAN_LCR_STATE_OUT_DIALING.
53
54
55 Call is released by LCR:
56
57 A MESSAGE_RELEASE is received with the call reference (ref) to be released.
58 The current ref is set to 0, to indicate released reference.
59 The state changes to CHAN_LCR_STATE_RELEASE.
60 ast_queue_hangup() is called, if asterisk instance (ast) exists, if not,
61 the chan_call instance is destroyed.
62 After lcr_hangup() is called-back by Asterisk, the chan_call instance
63 is destroyed, because the current ref is set to 0 and the state equals
64 CHAN_LCR_STATE_RELEASE.
65 If the ref is 0 and the state is not CHAN_LCR_STATE_RELEASE, see the proceedure
66 "Call is released by Asterisk".
67
68
69 Call is released by Asterisk:
70
71 lcr_hangup() is called-back by Asterisk. If the call reference (ref) is set,
72 a MESSAGE_RELEASE is sent to LCR and the chan_call instance is destroyed.
73 If the ref is 0 and the state is not CHAN_LCR_STATE_RELEASE, the new state is
74 set to CHAN_LCR_STATE_RELEASE.
75 Later, if the MESSAGE_NEWREF reply is received, a MESSAGE_RELEASE is sent to
76 LCR and the chan_call instance is destroyed.
77 If the ref is 0 and the state is CHAN_LCR_STATE_RELEASE, see the proceedure
78 "Call is released by LCR".
79
80 */
81
82 locking asterisk process and handler
83 reconnect after socket closed, release all calls.
84 debug of call handling
85 denke an alle info-elements in jeder message (from asterisk & from lcr)
86 ausloesen beim socket-verlust
87
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <string.h>
91 #include <stdarg.h>
92 #include <errno.h>
93 #include <sys/types.h>
94 #include <time.h>
95 #include <unistd.h>
96 #include <fcntl.h>
97 #include <sys/ioctl.h>
98 #include <sys/socket.h>
99 #include <sys/un.h>
100
101 #include <pthread.h>
102 #include <semaphore.h>
103
104 #include "extension.h"
105 #include "message.h"
106 #include "lcrsocket.h"
107 #include "cause.h"
108 #include "bchannel.h"
109 #include "chan_lcr.h"
110
111
112
113 #include <asterisk/module.h>
114 #include <asterisk/channel.h>
115 #include <asterisk/config.h>
116 #include <asterisk/logger.h>
117 #include <asterisk/pbx.h>
118 #include <asterisk/options.h>
119 #include <asterisk/io.h>
120 #include <asterisk/frame.h>
121 #include <asterisk/translate.h>
122 #include <asterisk/cli.h>
123 #include <asterisk/musiconhold.h>
124 #include <asterisk/dsp.h>
125 #include <asterisk/translate.h>
126 #include <asterisk/file.h>
127 #include <asterisk/callerid.h>
128 #include <asterisk/indications.h>
129 #include <asterisk/app.h>
130 #include <asterisk/features.h>
131 #include <asterisk/sched.h>
132
133 CHAN_LCR_STATE // state description structure
134
135 int lcr_debug=1;
136 int mISDN_created=1;
137
138 char lcr_type[]="LCR";
139
140 pthread_t chan_tid;
141 pthread_mutex_t chan_lock;
142 int quit;
143
144 int lcr_sock = -1;
145
146 struct admin_list {
147         struct admin_list *next;
148         struct admin_msg msg;
149 } *admin_first = NULL;
150
151 /*
152  * channel and call instances
153  */
154 struct chan_call *call_first;
155
156 struct chan_call *find_call_ref(unsigned long ref)
157 {
158         struct chan_call *call = call_first;
159
160         while(call)
161         {
162                 if (call->ref == ref)
163                         break;
164                 call = call->next;
165         }
166         return(call);
167 }
168
169 struct chan_call *find_call_handle(unsigned long handle)
170 {
171         struct chan_call *call = call_first;
172
173         while(call)
174         {
175                 if (call->bchannel_handle == handle)
176                         break;
177                 call = call->next;
178         }
179         return(call);
180 }
181
182 struct chan_call *alloc_call(void)
183 {
184         struct chan_call **callp = &call_first;
185
186         while(*callp)
187                 callp = &((*callp)->next);
188
189         *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
190         if (*callp)
191                 memset(*callp, 0, sizeof(struct chan_call));
192         return(*callp);
193 }
194
195 void free_call(struct chan_call *call)
196 {
197         struct chan_call **temp = &call_first;
198
199         while(*temp)
200         {
201                 if (*temp == call)
202                 {
203                         *temp = (*temp)->next;
204                         free(call);
205                         return;
206                 }
207                 temp = &((*temp)->next);
208         }
209 }
210
211 unsigned short new_brige_id(void)
212 {
213         struct chan_call *call;
214         unsigned short id = 1;
215
216         /* search for lowest bridge id that is not in use and not 0 */
217         while(id)
218         {
219                 call = call_first;
220                 while(call)
221                 {
222                         if (call->bridge_id == id)
223                                 break;
224                         call = call->next;
225                 }
226                 if (!call)
227                         break;
228                 id++;
229         }
230         return(id);
231 }
232
233
234 /*
235  * receive bchannel data
236  */
237 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
238 {
239 }
240
241 void rx_dtmf(struct bchannel *bchannel, char tone)
242 {
243 }
244
245 /*
246  * enque message to LCR
247  */
248 int send_message(int message_type, unsigned long ref, union parameter *param)
249 {
250         struct admin_list *admin, **adminp;
251
252         adminp = &admin_first;
253         while(*adminp)
254                 adminp = &((*adminp)->next);
255         admin = (struct admin_list *)malloc(sizeof(struct admin_list));
256         *adminp = admin;
257
258         admin->msg.type = message_type;
259         admin->msg.ref = ref;
260         memcpy(&admin->msg.param, param, sizeof(union parameter));
261
262         return(0);
263 }
264
265 /*
266  * incoming setup from LCR
267  */
268 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
269 {
270         struct ast_channel *ast;
271         union parameter newparam;
272
273         /* create asterisk channel instrance */
274         ast = ast_channel_alloc(1);
275         if (!ast)
276         {
277                 /* release */
278                 memset(&newparam, 0, sizeof(union parameter));
279                 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
280                 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
281                 send_message(MESSAGE_RELEASE, call->ref, &newparam);
282                 /* remove call */
283                 free_call(call);
284                 return;
285         }
286         /* set ast pointer */
287         call->ast = ast;
288         
289         /* fill setup information */
290 #warning todo: setup-info reinschreiben
291
292         /* send setup to asterisk */
293 #warning todo: setup bei der asterisk triggern
294
295         /* change state */
296         call->state = CHAN_LCR_STATE_IN_SETUP;
297 }
298
299 /*
300  * incoming setup acknowledge from LCR
301  */
302 static void lcr_in_overlap(struct chan_call *call, int message_type, union parameter *param)
303 {
304         /* send pending digits in dialque */
305         if (call->dialque)
306                 send_dialing_to_lcr(call);
307         /* change to overlap state */
308         call->state = CHAN_LCR_STATE_OUT_DIALING;
309 }
310
311 /*
312  * incoming proceeding from LCR
313  */
314 static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
315 {
316         /* change state */
317         call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
318         /* send event to asterisk */
319         ast_queue_... todo
320 }
321
322 /*
323  * incoming alerting from LCR
324  */
325 static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
326 {
327         /* change state */
328         call->state = CHAN_LCR_STATE_OUT_ALERTING;
329         /* send event to asterisk */
330         ast_queue_... todo
331 }
332
333 /*
334  * incoming connect from LCR
335  */
336 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
337 {
338         /* change state */
339         call->state = CHAN_LCR_STATE_CONNECT;
340         /* copy connectinfo */
341         todo
342         /* send event to asterisk */
343         ast_queue_... todo
344 }
345
346 /*
347  * incoming disconnect from LCR
348  */
349 static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param)
350 {
351         /* change state */
352         call->state = CHAN_LCR_STATE_IN_DISCONNECT;
353         /* copy disconnect info */
354         todo
355         /* send event to asterisk */
356         ast_queue_... todo
357 }
358
359 /*
360  * incoming setup acknowledge from LCR
361  */
362 static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param)
363 {
364         /* release ref */
365         call->ref = NULL;
366         /* change to release state */
367         call->state = CHAN_LCR_STATE_RELEASE;
368         /* copy release info */
369         todo
370         /* if we have an asterisk instance, send hangup, else we are done */
371         if (call->ast)
372         {
373                 ast_queue_hangup(call->ast);
374         } else
375         {
376                 free_call(call);
377         }
378         
379 }
380
381 /*
382  * incoming information from LCR
383  */
384 static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param)
385 {
386         /* copy digits */
387         todo and write them, maybe queue them for asterisk
388         /* send event to asterisk */
389         ast_queue_... todo
390 }
391
392 /*
393  * incoming information from LCR
394  */
395 static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
396 {
397         /* copy progress info */
398         todo and write them, maybe queue them for asterisk
399         /* send event to asterisk */
400         ast_queue_... todo
401         or maybe use bride info to forward facility.
402 }
403
404 /*
405  * message received from LCR
406  */
407 int receive_message(int message_type, unsigned long ref, union parameter *param)
408 {
409         union parameter newparam;
410         struct bchannel *bchannel;
411         struct chan_call *call;
412
413         memset(&newparam, 0, sizeof(union parameter));
414
415         /* handle bchannel message*/
416         if (message_type == MESSAGE_BCHANNEL)
417         {
418                 switch(param->bchannel.type)
419                 {
420                         case BCHANNEL_ASSIGN:
421                         if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
422                         {
423                                 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
424                                 return(-1);
425                         }
426                         /* create bchannel */
427                         bchannel = alloc_bchannel(param->bchannel.handle);
428                         if (!bchannel)
429                         {
430                                 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
431                                 return(-1);
432                         }
433
434                         /* configure channel */
435                         bchannel->b_tx_gain = param->bchannel.tx_gain;
436                         bchannel->b_rx_gain = param->bchannel.rx_gain;
437                         strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
438                         if (param->bchannel.crypt_len)
439                         {
440                                 bchannel->b_crypt_len = param->bchannel.crypt_len;
441                                 bchannel->b_crypt_type = param->bchannel.crypt_type;
442                                 memcpy(bchannel->b_crypt_key, param->bchannel.crypt, param->bchannel.crypt_len);
443                         }
444                         bchannel->b_txdata = 0;
445                         bchannel->b_dtmf = 1;
446                         bchannel->b_tx_dejitter = 1;
447
448                         /* in case, ref is not set, this bchannel instance must
449                          * be created until it is removed again by LCR */
450                         /* link to call */
451                         if ((call = find_call_ref(ref)))
452                         {
453                                 bchannel->ref = ref;
454                                 call->bchannel_handle = param->bchannel.handle;
455 #warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
456                                 bchannel_join(bchannel, call->bridge_id);
457                         }
458                         if (bchannel_create(bchannel))
459                                 bchannel_activate(bchannel, 1);
460
461                         /* acknowledge */
462                         newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
463                         newparam.bchannel.handle = param->bchannel.handle;
464                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
465                         break;
466
467                         case BCHANNEL_REMOVE:
468                         if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
469                         {
470                                 #warning alle fprintf nach ast_log
471                                 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
472                                 return(-1);
473                         }
474                         /* unlink from call */
475                         if ((call = find_call_ref(bchannel->ref)))
476                         {
477                                 call->bchannel_handle = 0;
478                         }
479                         /* destroy and remove bchannel */
480                         free_bchannel(bchannel);
481
482                         /* acknowledge */
483                         newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
484                         newparam.bchannel.handle = param->bchannel.handle;
485                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
486                         
487                         break;
488
489                         default:
490                         fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
491                 }
492                 return(0);
493         }
494
495         /* handle new ref */
496         if (message_type == MESSAGE_NEWREF)
497         {
498                 if (param->direction)
499                 {
500                         /* new ref from lcr */
501                         if (!ref || find_call_ref(ref))
502                         {
503                                 fprintf(stderr, "illegal new ref %d received\n", ref);
504                                 return(-1);
505                         }
506                         /* allocate new call instance */
507                         call = alloc_call();
508                         /* new state */
509                         call->state = CHAN_LCR_STATE_IN_PREPARE;
510                         /* set ref */
511                         call->ref = ref;
512                         /* wait for setup (or release from asterisk) */
513                 } else
514                 {
515                         /* new ref, as requested from this remote application */
516                         call = find_call_ref(0);
517                         if (!call)
518                         {
519                                 /* send release, if ref does not exist */
520                                 newparam.disconnectinfo.cause = CAUSE_NORMAL;
521                                 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
522                                 send_message(MESSAGE_RELEASE, ref, &newparam);
523                                 return(0);
524                         }
525                         /* store new ref */
526                         call->ref = ref;
527                         /* send pending setup info */
528                         if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
529                                 send_setup_to_lcr(call);
530                         /* release if asterisk has signed off */
531                         else if (call->state == CHAN_LCR_STATE_RELEASE)
532                         {
533                                 /* send release */
534                                 newparam.disconnectinfo.cause = todo
535                                 newparam.disconnectinfo.location = todo
536                                 send_message(MESSAGE_RELEASE, ref, &newparam);
537                                 /* free call */
538                                 free_call(call);
539                                 return(0);
540                         }
541                 }
542                 return(0);
543         }
544
545         /* check ref */
546         if (!ref)
547         {
548                 fprintf(stderr, "received message %d without ref\n", message_type);
549                 return(-1);
550         }
551         call = find_call_ref(ref);
552         if (!call)
553         {
554                 /* ignore ref that is not used (anymore) */
555                 return(0);
556         }
557
558         /* handle messages */
559         switch(message_type)
560         {
561                 case MESSAGE_SETUP:
562                 lcr_in_setup(call, message_type, param);
563                 break;
564
565                 case MESSAGE_OVERLAP:
566                 lcr_in_overlap(call, message_type, param);
567                 break;
568
569                 case MESSAGE_PROCEEDING:
570                 lcr_in_proceeding(call, message_type, param);
571                 break;
572
573                 case MESSAGE_ALERTING:
574                 lcr_in_alerting(call, message_type, param);
575                 break;
576
577                 case MESSAGE_CONNECT:
578                 lcr_in_connect(call, message_type, param);
579                 break;
580
581                 case MESSAGE_DISCONNECT:
582                 lcr_in_disconnect(call, message_type, param);
583                 break;
584
585                 case MESSAGE_RELEASE:
586                 lcr_in_release(call, message_type, param);
587                 break;
588
589                 case MESSAGE_INFORMATION:
590                 lcr_in_disconnect(call, message_type, param);
591                 break;
592
593                 case MESSAGE_FACILITY:
594                 lcr_in_disconnect(call, message_type, param);
595                 break;
596
597                 case MESSAGE_PATTERN:
598 #warning todo
599                 break;
600
601                 case MESSAGE_NOPATTERN:
602 #warning todo
603                 break;
604
605                 case MESSAGE_AUDIOPATH:
606 #warning todo
607                 break;
608
609                 default:
610 #warning unhandled
611         }
612         return(0);
613 }
614
615
616 /* asterisk handler
617  * warning! not thread safe
618  * returns -1 for socket error, 0 for no work, 1 for work
619  */
620 int handle_socket(void)
621 {
622         int work = 0;
623         int len;
624         struct admin_message msg;
625         struct admin_list *admin;
626
627         int sock;
628
629         #warning SOCKET FEHLT!
630         /* read from socket */
631         len = read(sock, &msg, sizeof(msg));
632         if (len == 0)
633         {
634                 printf("Socket closed\n");
635                 return(-1); // socket closed
636         }
637         if (len > 0)
638         {
639                 if (len != sizeof(msg))
640                 {
641                         fprintf(stderr, "Socket short read (%d)\n", len);
642                         return(-1); // socket error
643                 }
644                 if (msg.message != ADMIN_MESSAGE)
645                 {
646                         fprintf(stderr, "Socket received illegal message %d\n", msg.message);
647                         return(-1); // socket error
648                 }
649                 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
650                 printf("message received %d\n", msg.u.msg.type);
651                 work = 1;
652         } else
653         {
654                 if (errno != EWOULDBLOCK)
655                 {
656                         fprintf(stderr, "Socket error %d\n", errno);
657                         return(-1);
658                 }
659         }
660
661         /* write to socket */
662         if (!admin_first)
663                 return(work);
664         admin = admin_first;
665         len = write(sock, &admin->msg, sizeof(msg));
666         if (len == 0)
667         {
668                 printf("Socket closed\n");
669                 return(-1); // socket closed
670         }
671         if (len > 0)
672         {
673                 if (len != sizeof(msg))
674                 {
675                         fprintf(stderr, "Socket short write (%d)\n", len);
676                         return(-1); // socket error
677                 }
678                 /* free head */
679                 admin_first = admin->next;
680                 free(admin);
681
682                 work = 1;
683         } else
684         {
685                 if (errno != EWOULDBLOCK)
686                 {
687                         fprintf(stderr, "Socket error %d\n", errno);
688                         return(-1);
689                 }
690         }
691
692         return(work);
693 }
694
695 /*
696  * open and close socket
697  */
698 int open_socket(void)
699 {
700         int ret;
701         int sock;
702         char *socket_name = SOCKET_NAME;
703         int conn;
704         struct sockaddr_un sock_address;
705         unsigned long on = 1;
706         union parameter param;
707
708         /* open socket */
709         if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
710         {
711                 ast_log(LOG_ERROR, "Failed to create socket.\n");
712                 return(sock);
713         }
714
715         /* set socket address and name */
716         memset(&sock_address, 0, sizeof(sock_address));
717         sock_address.sun_family = PF_UNIX;
718         strcpy(sock_address.sun_path, socket_name);
719
720         /* connect socket */
721         if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
722         {
723                 close(sock);
724                 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
725                 return(conn);
726         }
727
728         /* set non-blocking io */
729         if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
730         {
731                 close(sock);
732                 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
733                 return(ret);
734         }
735
736         /* enque hello message */
737         memset(&param, 0, sizeof(param));
738         strcpy(param.hello.application, "asterisk");
739         send_message(MESSAGE_HELLO, 0, &param);
740
741         return(sock);
742 }
743
744 void close_socket(int sock)
745 {
746         /* close socket */
747         if (socket >= 0)        
748                 close(sock);
749 }
750
751
752 socket muss per timer fuer das Ã¶ffnen checken
753 static void *chan_thread(void *arg)
754 {
755         int work;
756
757         while(!quit)
758         {
759                 work = 0;
760
761                 /* handle socket */
762                 int ret = handle_socket();
763                 if (ret < 0)
764                         break;
765                 if (ret)
766                         work = 1;
767
768                 /* handle mISDN */
769                 ret = bchannel_handle();
770                 if (ret)
771                         work = 1;
772                 
773                 if (!work)
774                 {
775                         pthread_mutex_unlock(&chan_lock);
776                         usleep(30000);
777                         pthread_mutex_lock(&chan_lock);
778                 }
779         }
780         return NULL;
781 }
782
783 /*
784  * send setup info to LCR
785  * this function is called, when asterisk call is received and ref is received
786  */
787 static void send_setup_to_lcr(struct chan_call *call)
788 {
789         if (!ast || !call->ref)
790                 return;
791
792         /* send setup message to LCR */
793         memset(&newparam, 0, sizeof(union parameter));
794         newparam.setup.xxxxxx = 
795         send_message(MESSAGE_SETUP, call->ref, &newparam);
796         /* change to outgoing setup state */
797         call->state = CHAN_LCR_STATE_OUT_SETUP;
798 }
799
800 #if 0
801 CHRISTIAN: das war ein konflikt beim pullen
802 siehe anderes lcr_request();
803 bedenke: das ast_log muss noch Ã¼eberall eingepflegt werden
804
805 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
806 {
807         struct chan_call *call=alloc_call();
808
809         if (call) {
810 #warning hier muss jetzt wohl eine Ref angefordert werden!
811                 ast=lcr_ast_new(call, ext, NULL, 0 );
812
813                 if (ast) {
814                         call->ast=ast;
815                 } else {
816                         ast_log(LOG_WARNING, "Could not create new Asterisk Channel\n");
817                         free_call(call);
818                 }
819         } else {
820                 ast_log(LOG_WARNING, "Could not create new Lcr Call Handle\n");
821         }
822
823         return ast;
824 }
825
826         struct ast_channel *ast=NULL;
827
828         char buf[128];
829         char *port_str, *ext, *p;
830         int port;
831
832         ast_copy_string(buf, data, sizeof(buf)-1);
833         p=buf;
834         port_str=strsep(&p, "/");
835         ext=strsep(&p, "/");
836         ast_verbose("portstr:%s ext:%s\n",port_str, ext);
837
838         sprintf(buf,"%s/%s",lcr_type,(char*)data);
839 #endif
840
841 /*
842  * send dialing info to LCR
843  * this function is called, when setup acknowledge is received and dialing
844  * info is available.
845  */
846 static void send_dialing_to_lcr(struct chan_call *call)
847 {
848         if (!ast || !call->ref || !call->dialque)
849                 return;
850         
851         /* send setup message to LCR */
852         memset(&newparam, 0, sizeof(union parameter));
853         strncpy(newparam.dialinginfo.id, call->dialque, sizeof(newparam.dialinginfo.id)-1);
854         call->dialque[0] = '\0';
855         send_message(MESSAGE_INFORMATION, call->ref, &newparam);
856 }
857
858 /*
859  * new asterisk instance
860  */
861 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
862 {
863         pthread_mutex_lock(&chan_lock);
864
865         /* create call instance */
866         call = alloc_call();
867         if (!call)
868         {
869                 /* failed to create instance */
870                 return NULL;
871         }
872         /* create asterisk channel instrance */
873         ast = ast_channel_alloc(1);
874         if (!ast)
875         {
876                 free_call(call);
877                 /* failed to create instance */
878                 return NULL;
879         }
880         /* link together */
881         ast->tech_pvt = call;
882         call->ast = ast;
883         /* send MESSAGE_NEWREF */
884         memset(&newparam, 0, sizeof(union parameter));
885         newparam.direction = 0; /* request from app */
886         send_message(MESSAGE_NEWREF, 0, &newparam);
887         /* set state */
888         call->state = CHAN_LCR_STATE_OUT_PREPARE;
889
890         pthread_mutex_unlock(&chan_lock);
891 }
892
893 /*
894  * call from asterisk
895  */
896 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
897 {
898         struct chan_call *call=ast->tech_pvt;
899         char buf[128];
900         char *port_str, *dad, *p;
901
902         if (!call) return -1;
903
904         pthread_mutex_lock(&chan_lock);
905
906         hier muss noch
907         ast_copy_string(buf, dest, sizeof(buf)-1);
908         p=buf;
909         port_str=strsep(&p, "/");
910         dad=strsep(&p, "/");
911
912         /* send setup message, if we already have a callref */
913         if (call->ref)
914                 send_setup_to_lcr(call);
915
916         if (lcr_debug)
917                 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
918
919 #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.
920         
921         pthread_mutex_unlock(&chan_lock);
922         return 0; 
923 }
924
925 static int lcr_digit(struct ast_channel *ast, char digit)
926 {
927         char buf[]="x";
928
929         if (!call) return -1;
930
931         /* only pass IA5 number space */
932         if (digit > 126 || digit < 32)
933                 return 0;
934
935         pthread_mutex_lock(&chan_lock);
936
937         /* send information or queue them */
938         if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
939         {
940                 send_dialing_to_lcr(call);
941         } else
942         if (!call->ref
943          && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
944         {
945                 *buf = digit;
946                 strncat(call->dialque, buf, strlen(char->dialque)-1);
947         } else
948         {
949 digits kommen, koennen aber nicht verwendet werden.
950         sollen wir sie als info senden (im connect zb.)
951         }
952
953         pthread_mutex_unlock(&chan_lock);
954         
955         return(0);
956 }
957
958 static int lcr_answer(struct ast_channel *c)
959 {
960         struct chan_call *call=c->tech_pvt;
961         if (!call) return -1;
962         pthread_mutex_lock(&chan_lock);
963         pthread_mutex_unlock(&chan_lock);
964         return 0;
965 }
966
967 static int lcr_hangup(struct ast_channel *ast)
968 {
969         struct chan_call *call = ast->tech_pvt;
970
971         if (!call)
972                 return 0;
973
974         pthread_mutex_lock(&chan_lock);
975         /* disconnect asterisk, maybe not required */
976         ast->tech_pvt = NULL;
977         if (call->ref)
978         {
979                 /* release */
980                 memset(&newparam, 0, sizeof(union parameter));
981                 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
982                 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
983                 send_message(MESSAGE_RELEASE, call->ref, &newparam);
984                 /* remove call */
985                 free_call(call);
986                 pthread_mutex_unlock(&chan_lock);
987                 return 0;
988         } else
989         {
990                 /* ref is not set, due to prepare setup or release */
991                 if (call->state == CHAN_LCR_STATE_RELEASE)
992                 {
993                         /* we get the response to our release */
994                         free_call(call);
995                 } else
996                 {
997                         /* during prepare, we change to release state */
998                         call->state = CHAN_LCR_STATE_RELEASE;
999                 }
1000         } 
1001         pthread_mutex_unlock(&chan_lock);
1002         return 0;
1003 }
1004
1005 static int lcr_write(struct ast_channel *c, struct ast_frame *f)
1006 {
1007         struct chan_call *call= c->tech_pvt;
1008         if (!call) return 0;
1009         pthread_mutex_lock(&chan_lock);
1010         pthread_mutex_unlock(&chan_lock);
1011 }
1012
1013
1014 static struct ast_frame *lcr_read(struct ast_channel *c)
1015 {
1016         struct chan_call *call = c->tech_pvt;
1017         if (!call) return 0;
1018         pthread_mutex_lock(&chan_lock);
1019         pthread_mutex_unlock(&chan_lock);
1020 }
1021
1022 static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
1023 {
1024         int res = -1;
1025         if (!call) return -1;
1026
1027         pthread_mutex_lock(&chan_lock);
1028
1029         switch (cond) {
1030                 case AST_CONTROL_BUSY:
1031                 case AST_CONTROL_CONGESTION:
1032                 case AST_CONTROL_RINGING:
1033                         pthread_mutex_unlock(&chan_lock);
1034                         return -1;
1035                 case -1:
1036                         pthread_mutex_unlock(&chan_lock);
1037                         return 0;
1038
1039                 case AST_CONTROL_VIDUPDATE:
1040                         res = -1;
1041                         break;
1042                 case AST_CONTROL_HOLD:
1043                         ast_verbose(" << Console Has Been Placed on Hold >> \n");
1044                         //ast_moh_start(c, data, g->mohinterpret);
1045                         break;
1046                 case AST_CONTROL_UNHOLD:
1047                         ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
1048                         //ast_moh_stop(c);
1049                         break;
1050
1051                 default:
1052                         ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
1053                         pthread_mutex_unlock(&chan_lock);
1054                         return -1;
1055         }
1056
1057         pthread_mutex_unlock(&chan_lock);
1058         return 0;
1059 }
1060
1061 static struct ast_channel_tech lcr_tech = {
1062         .type=lcr_type,
1063         .description="Channel driver for connecting to Linux-Call-Router",
1064         .capabilities=AST_FORMAT_ALAW,
1065         .requester=lcr_request,
1066         .send_digit=lcr_digit,
1067         .call=lcr_call,
1068 //      .bridge=lcr_bridge, 
1069         .hangup=lcr_hangup,
1070         .answer=lcr_answer,
1071         .read=lcr_read,
1072         .write=lcr_write,
1073         .indicate=lcr_indicate,
1074 //      .fixup=lcr_fixup,
1075 //      .send_text=lcr_send_text,
1076         .properties=0
1077 };
1078
1079 #warning das muss mal aus der config datei gelesen werden:
1080 char lcr_context[]="from-lcr";
1081
1082 static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref)
1083 {
1084         struct ast_channel *tmp;
1085         char *cid_name = 0, *cid_num = 0;
1086
1087
1088         if (callerid)
1089                 ast_callerid_parse(callerid, &cid_name, &cid_num);
1090
1091         tmp = ast_channel_alloc(1, AST_STATE_RESERVED, cid_num, cid_name, "", exten, "", 0, "%s/%d", lcr_type,  ref);
1092
1093         if (tmp) {
1094                 tmp->tech = &lcr_tech;
1095                 tmp->writeformat = AST_FORMAT_ALAW;
1096                 tmp->readformat = AST_FORMAT_ALAW;
1097
1098                 ast_copy_string(tmp->context, lcr_context, AST_MAX_CONTEXT);
1099
1100         }
1101
1102         return tmp;
1103 }
1104
1105
1106
1107 /*
1108  * cli
1109  */
1110 static int lcr_show_lcr (int fd, int argc, char *argv[])
1111 {
1112 }
1113
1114 static int lcr_show_calls (int fd, int argc, char *argv[])
1115 {
1116 }
1117
1118 static int lcr_reload_routing (int fd, int argc, char *argv[])
1119 {
1120 }
1121
1122 static int lcr_reload_interfaces (int fd, int argc, char *argv[])
1123 {
1124 }
1125
1126 static int lcr_port_block (int fd, int argc, char *argv[])
1127 {
1128 }
1129
1130 static int lcr_port_unblock (int fd, int argc, char *argv[])
1131 {
1132 }
1133
1134 static int lcr_port_unload (int fd, int argc, char *argv[])
1135 {
1136 }
1137
1138 static struct ast_cli_entry cli_show_lcr =
1139 { {"lcr", "show", "lcr", NULL},
1140  lcr_show_lcr,
1141  "Shows current states of LCR core",
1142  "Usage: lcr show lcr\n",
1143 };
1144
1145 static struct ast_cli_entry cli_show_calls =
1146 { {"lcr", "show", "calls", NULL},
1147  lcr_show_calls,
1148  "Shows current calls made by LCR and Asterisk",
1149  "Usage: lcr show calls\n",
1150 };
1151
1152 static struct ast_cli_entry cli_reload_routing =
1153 { {"lcr", "reload", "routing", NULL},
1154  lcr_reload_routing,
1155  "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
1156  "Usage: lcr reload routing\n",
1157 };
1158
1159 static struct ast_cli_entry cli_reload_interfaces =
1160 { {"lcr", "reload", "interfaces", NULL},
1161  lcr_reload_interfaces,
1162  "Reloads interfaces conf of LCR",
1163  "Usage: lcr reload interfaces\n",
1164 };
1165
1166 static struct ast_cli_entry cli_port_block =
1167 { {"lcr", "port", "block", NULL},
1168  lcr_port_block,
1169  "Blocks LCR port for further calls",
1170  "Usage: lcr port block \"<port>\"\n",
1171 };
1172
1173 static struct ast_cli_entry cli_port_unblock =
1174 { {"lcr", "port", "unblock", NULL},
1175  lcr_port_unblock,
1176  "Unblocks or loads LCR port, port is opened my mISDN",
1177  "Usage: lcr port unblock \"<port>\"\n",
1178 };
1179
1180 static struct ast_cli_entry cli_port_unload =
1181 { {"lcr", "port", "unload", NULL},
1182  lcr_port_unload,
1183  "Unloads LCR port, port is closes by mISDN",
1184  "Usage: lcr port unload \"<port>\"\n",
1185 };
1186
1187
1188 /*
1189  * module loading and destruction
1190  */
1191 int load_module(void)
1192 {
1193 //      ast_mutex_init(&release_lock);
1194
1195 //      lcr_cfg_update_ptp();
1196
1197         pthread_mutex_init(&chan_lock, NULL);
1198         
1199         if (!(lcr_sock = open_socket())) {
1200                 ast_log(LOG_ERROR, "Unable to connect\n");
1201                 lcr_sock = -1;
1202                 /* continue with closed socket */
1203         }
1204
1205         if (!bchannel_initialize()) {
1206                 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
1207                 return -1;
1208         }
1209         mISDN_created = 1;
1210
1211         if (ast_channel_register(&lcr_tech)) {
1212                 ast_log(LOG_ERROR, "Unable to register channel class\n");
1213                 return -1;
1214         }
1215  
1216 #if 0   
1217         ast_cli_register(&cli_show_lcr);
1218         ast_cli_register(&cli_show_calls);
1219
1220         ast_cli_register(&cli_reload_routing);
1221         ast_cli_register(&cli_reload_interfaces);
1222         ast_cli_register(&cli_port_block);
1223         ast_cli_register(&cli_port_unblock);
1224         ast_cli_register(&cli_port_unload);
1225   
1226         ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
1227                                  "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
1228                                  "Sets mISDN opts. and optargs\n"
1229                                  "\n"
1230                                  "The available options are:\n"
1231                                  "    d - Send display text on called phone, text is the optparam\n"
1232                                  "    n - don't detect dtmf tones on called channel\n"
1233                                  "    h - make digital outgoing call\n" 
1234                                  "    c - make crypted outgoing call, param is keyindex\n"
1235                                  "    e - perform echo cancelation on this channel,\n"
1236                                  "        takes taps as arguments (32,64,128,256)\n"
1237                                  "    s - send Non Inband DTMF as inband\n"
1238                                  "   vr - rxgain control\n"
1239                                  "   vt - txgain control\n"
1240                 );
1241
1242         
1243         lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1244
1245         chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
1246 =======
1247         //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1248 #endif
1249
1250         quit = 1;       
1251         if ((pthread_create(&chan_tid, NULL, chan_thread, arg)<0))
1252         {
1253                 failed to create thread
1254                 return -1;
1255         }
1256         return 0;
1257 }
1258
1259 int unload_module(void)
1260 {
1261         /* First, take us out of the channel loop */
1262         ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
1263
1264         quit = 1;
1265         pthread_join(chan_tid, NULL);   
1266         
1267         ast_channel_unregister(&lcr_tech);
1268
1269         if (mISDN_created) {
1270                 bchannel_deinitialize();
1271                 mISDN_created = 0;
1272         }
1273
1274         if (lcr_sock >= 0) {
1275                 close(lcr_sock);
1276                 lcr_sock = -1;
1277         }
1278
1279         return 0;
1280 }
1281
1282 static int reload_module(void)
1283 {
1284 //      reload_config();
1285         return 0;
1286 }
1287
1288
1289 ast_mutex_t usecnt_lock;
1290 int usecnt;
1291
1292 int usecount(void)
1293 {
1294         int res;
1295         ast_mutex_lock(&usecnt_lock);
1296         res = usecnt;
1297         ast_mutex_unlock(&usecnt_lock);
1298         return res;
1299 }
1300
1301
1302 char *desc="Channel driver for lcr";
1303
1304 char *description(void)
1305 {
1306         return desc;
1307 }
1308
1309 char *key(void)
1310 {
1311         return ASTERISK_GPL_KEY;
1312 }
1313
1314 #define AST_MODULE "chan_lcr"
1315 AST_MODULE_INFO(ASTERISK_GPL_KEY,
1316                                 AST_MODFLAG_DEFAULT,
1317                                 "Channel driver for LCR",
1318                                 .load = load_module,
1319                                 .unload = unload_module,
1320                                 .reload = reload_module,
1321                            );
1322