work on chan_lcr
[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 todo (before first compile)
83 reconnect after socket closed, release all calls.
84 debug of call handling
85 ausloesen beim socket-verlust
86
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                         if (call->bch)
205                         {
206                                 if (call->bch->call)
207                                         call->bch->call = NULL;
208                         }
209                         free(call);
210                         return;
211                 }
212                 temp = &((*temp)->next);
213         }
214 }
215
216 unsigned short new_brige_id(void)
217 {
218         struct chan_call *call;
219         unsigned short id = 1;
220
221         /* search for lowest bridge id that is not in use and not 0 */
222         while(id)
223         {
224                 call = call_first;
225                 while(call)
226                 {
227                         if (call->bridge_id == id)
228                                 break;
229                         call = call->next;
230                 }
231                 if (!call)
232                         break;
233                 id++;
234         }
235         return(id);
236 }
237
238
239 /*
240  * receive bchannel data
241  */
242 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
243 {
244 }
245
246 void rx_dtmf(struct bchannel *bchannel, char tone)
247 {
248 }
249
250 /*
251  * enque message to LCR
252  */
253 int send_message(int message_type, unsigned long ref, union parameter *param)
254 {
255         struct admin_list *admin, **adminp;
256
257         adminp = &admin_first;
258         while(*adminp)
259                 adminp = &((*adminp)->next);
260         admin = (struct admin_list *)malloc(sizeof(struct admin_list));
261         *adminp = admin;
262
263         admin->msg.type = message_type;
264         admin->msg.ref = ref;
265         memcpy(&admin->msg.param, param, sizeof(union parameter));
266
267         return(0);
268 }
269
270 /*
271  * in case of a bridge, the unsupported message can be forwarded directly
272  * to the remote call.
273  */
274 static void bridge_message_if_bridged(struct chan_call *call, int message_type, union parameter *param)
275 {
276         /* check bridge */
277         if (!call) return;
278         if (!call->channel) return;
279         if (!call->channel->bridge_channel) return;
280         if (!call->channel->bridge_channel->call) return;
281         if (!call->channel->bridge_channel->call->ref) return;
282         send_message(MESSAGE_RELEASE, call->channel->bridge_channel->call->ref, param);
283 }
284
285 /*
286  * incoming setup from LCR
287  */
288 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
289 {
290         struct ast_channel *ast;
291         union parameter newparam;
292
293         /* create asterisk channel instrance */
294         ast = ast_channel_alloc(1);
295         if (!ast)
296         {
297                 /* release */
298                 memset(&newparam, 0, sizeof(union parameter));
299                 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
300                 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
301                 send_message(MESSAGE_RELEASE, call->ref, &newparam);
302                 /* remove call */
303                 free_call(call);
304                 return;
305         }
306         /* set ast pointer */
307         call->ast = ast;
308         ast->tech_pvt = call;
309         ast->tech = &lcr_tech;
310         
311         /* fill setup information */
312         if (param->setup.exten[0])
313                 strdup(ast->exten, param->setup.exten);
314         if (param->setup.callerinfo.id[0])
315                 strdup(ast->cid->cid_num, param->setup.callerinfo.id);
316         if (param->setup.callerinfo.name[0])
317                 strdup(ast->cid->cid_name, param->setup.callerinfo.name);
318         if (param->setup.redirinfo.id[0])
319                 strdup(ast->cid->cid_name, numberrize_callerinfo(param->setup.callerinfo.name, param->setup.callerinfo.ntype, configfile->prefix_nat, configfile->prefix_inter));
320         switch (param->setup.callerinfo.present)
321         {
322                 case INFO_PRESENT_ALLOWED:
323                         ast->cid->cid_pres = AST_PRESENT_ALLOWED;
324                 break;
325                 case INFO_PRESENT_RESTRICTED:
326                         ast->cid->cid_pres = AST_PRESENT_RESTRICTED;
327                 break;
328                 default:
329                         ast->cid->cid_pres = AST_PRESENT_UNAVAILABLE;
330         }
331         switch (param->setup.callerinfo.ntype)
332         {
333                 case INFO_NTYPE_SUBSCRIBER:
334                         ast->cid->cid_ton = AST_wasnu;
335                 break;
336                 case INFO_NTYPE_NATIONAL:
337                         ast->cid->cid_ton = AST_wasnu;
338                 break;
339                 case INFO_NTYPE_INTERNATIONAL:
340                         ast->cid->cid_ton = AST_wasnu;
341                 break;
342                 default:
343                         ast->cid->cid_ton = AST_wasnu;
344         }
345         ast->transfercapability = param->setup.bearerinfo.capability;
346
347         /* configure channel */
348         ast->state = AST_STATE_RESERVED;
349         snprintf(ast->name, sizeof(ast->name), "%s/%d", lcr_type, ++glob_channel);
350         ast->name[sizeof(ast->name)-1] = '\0';
351         ast->type = lcr_type;
352         ast->nativeformat = configfile->lawformat;
353         ast->readformat = ast->rawreadformat = configfile->lawformat;
354         ast->writeformat = ast->rawwriteformat = configfile->lawformat;
355         ast->hangupcause = 0;
356
357         /* change state */
358         call->state = CHAN_LCR_STATE_IN_SETUP;
359
360         /* send setup to asterisk */
361         ast_pbx_start(ast);
362
363         /* send setup acknowledge to lcr */
364         memset(&newparam, 0, sizeof(union parameter));
365         send_message(MESSAGE_OVERLAP, call->ref, &newparam);
366
367         /* change state */
368         call->state = CHAN_LCR_STATE_IN_DIALING;
369 }
370
371 /*
372  * incoming setup acknowledge from LCR
373  */
374 static void lcr_in_overlap(struct chan_call *call, int message_type, union parameter *param)
375 {
376         if (!call->ast) return;
377
378         /* send pending digits in dialque */
379         if (call->dialque)
380                 send_dialque_to_lcr(call);
381         /* change to overlap state */
382         call->state = CHAN_LCR_STATE_OUT_DIALING;
383 }
384
385 /*
386  * incoming proceeding from LCR
387  */
388 static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
389 {
390         /* change state */
391         call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
392         /* send event to asterisk */
393         if (call->ast)
394                 ast_queue_control(ast, AST_CONTROL_PROCEEDING);
395 }
396
397 /*
398  * incoming alerting from LCR
399  */
400 static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
401 {
402         /* change state */
403         call->state = CHAN_LCR_STATE_OUT_ALERTING;
404         /* send event to asterisk */
405         if (call->ast)
406                 ast_queue_control(ast, AST_CONTROL_RINGING);
407 }
408
409 /*
410  * incoming connect from LCR
411  */
412 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
413 {
414         /* change state */
415         call->state = CHAN_LCR_STATE_CONNECT;
416         /* copy connectinfo */
417         memcpy(call->connectinfo, param->connectinfo, sizeof(struct connect_info));
418         /* send event to asterisk */
419         if (call->ast)
420                 ast_queue_control(ast, AST_CONTROL_ANSWER);
421 }
422
423 /*
424  * incoming disconnect from LCR
425  */
426 static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param)
427 {
428         union parameter newparam;
429
430         /* change state */
431         call->state = CHAN_LCR_STATE_IN_DISCONNECT;
432         /* save cause */
433         call->cause = param.disconnectinfo.cause;
434         call->location = param.disconnectinfo.location;
435         /* if bridge, forward disconnect and return */
436         if (call->channel)
437                 if (call->channel->bridge_channel)
438                         if (call->channel->bridge_channel->call)
439                         {
440                                 bridge_message_if_bridged(call, message_type, param);
441                                 return;
442                         }
443         /* release lcr */
444         newparam.disconnectinfo.cause = CAUSE_NORMAL;
445         newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
446         send_message(MESSAGE_RELEASE, ref, &newparam);
447         ref = 0;
448         /* release asterisk */
449         call->ast->hangupcause = call->cause;
450         ast_queue_hangup(call->ast);
451         /* change to release state */
452         call->state = CHAN_LCR_STATE_RELEASE;
453 }
454
455 /*
456  * incoming setup acknowledge from LCR
457  */
458 static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param)
459 {
460         /* release ref */
461         call->ref = NULL;
462         /* change to release state */
463         call->state = CHAN_LCR_STATE_RELEASE;
464         /* copy release info */
465         if (!call->cause)
466                call->cause = param.disconnectinfo.cause;
467         /* if we have an asterisk instance, send hangup, else we are done */
468         if (call->ast)
469         {
470                 call->ast->hangupcause = call->cause;
471                 ast_queue_hangup(call->ast);
472         } else
473         {
474                 free_call(call);
475         }
476         
477 }
478
479 /*
480  * incoming information from LCR
481  */
482 static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param)
483 {
484         struct ast_frame fr;
485         char *p;
486
487         if (!call->ast) return;
488         
489         /* copy digits */
490         p = param->dialinginfo.id;
491         if (call->state == CHAN_LCR_STATE_IN_DIALING && *p)
492         {
493                 while (*p)
494                 {
495                         /* send digit to asterisk */
496                         memset(&fr, 0, sizeof(fr));
497                         fr.frametype = AST_FRAME_DTMF;
498                         fr.subclass = *p;
499                         fr.delivery = ast_tv(0, 0);
500                         ast_queue_frame(call->ast, &fr);
501                         p++;
502                 }
503         }
504         /* use bridge to forware message not supported by asterisk */
505         if (call->state == CHAN_LCR_STATE_CONNECT)
506                 bridge_message_if_bridged(call, message_type, param);
507 }
508
509 /*
510  * incoming information from LCR
511  */
512 static void lcr_in_notify(struct chan_call *call, int message_type, union parameter *param)
513 {
514         if (!call->ast) return;
515
516         /* use bridge to forware message not supported by asterisk */
517         bridge_message_if_bridged(call, message_type, param);
518 }
519
520 /*
521  * incoming information from LCR
522  */
523 static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
524 {
525         if (!call->ast) return;
526
527         /* use bridge to forware message not supported by asterisk */
528         bridge_message_if_bridged(call, message_type, param);
529 }
530
531 /*
532  * message received from LCR
533  */
534 int receive_message(int message_type, unsigned long ref, union parameter *param)
535 {
536         union parameter newparam;
537         struct bchannel *bchannel;
538         struct chan_call *call;
539
540         memset(&newparam, 0, sizeof(union parameter));
541
542         /* handle bchannel message*/
543         if (message_type == MESSAGE_BCHANNEL)
544         {
545                 switch(param->bchannel.type)
546                 {
547                         case BCHANNEL_ASSIGN:
548                         if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
549                         {
550                                 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
551                                 return(-1);
552                         }
553                         /* create bchannel */
554                         bchannel = alloc_bchannel(param->bchannel.handle);
555                         if (!bchannel)
556                         {
557                                 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
558                                 return(-1);
559                         }
560
561                         /* configure channel */
562                         bchannel->b_tx_gain = param->bchannel.tx_gain;
563                         bchannel->b_rx_gain = param->bchannel.rx_gain;
564                         strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
565                         if (param->bchannel.crypt_len)
566                         {
567                                 bchannel->b_crypt_len = param->bchannel.crypt_len;
568                                 bchannel->b_crypt_type = param->bchannel.crypt_type;
569                                 memcpy(bchannel->b_crypt_key, param->bchannel.crypt, param->bchannel.crypt_len);
570                         }
571                         bchannel->b_txdata = 0;
572                         bchannel->b_dtmf = 1;
573                         bchannel->b_tx_dejitter = 1;
574
575                         /* in case, ref is not set, this bchannel instance must
576                          * be created until it is removed again by LCR */
577                         /* link to call */
578                         if ((call = find_call_ref(ref)))
579                         {
580                                 bchannel->ref = ref;
581                                 call->bchannel_handle = param->bchannel.handle;
582 #warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
583                                 bchannel_join(bchannel, call->bridge_id);
584                         }
585                         if (bchannel_create(bchannel))
586                                 bchannel_activate(bchannel, 1);
587
588                         /* acknowledge */
589                         newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
590                         newparam.bchannel.handle = param->bchannel.handle;
591                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
592                         break;
593
594                         case BCHANNEL_REMOVE:
595                         if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
596                         {
597                                 #warning alle fprintf nach ast_log
598                                 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
599                                 return(-1);
600                         }
601                         /* unlink from call */
602                         if ((call = find_call_ref(bchannel->ref)))
603                         {
604                                 call->bchannel_handle = 0;
605                         }
606                         /* destroy and remove bchannel */
607                         free_bchannel(bchannel);
608
609                         /* acknowledge */
610                         newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
611                         newparam.bchannel.handle = param->bchannel.handle;
612                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
613                         
614                         break;
615
616                         default:
617                         fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
618                 }
619                 return(0);
620         }
621
622         /* handle new ref */
623         if (message_type == MESSAGE_NEWREF)
624         {
625                 if (param->direction)
626                 {
627                         /* new ref from lcr */
628                         if (!ref || find_call_ref(ref))
629                         {
630                                 fprintf(stderr, "illegal new ref %d received\n", ref);
631                                 return(-1);
632                         }
633                         /* allocate new call instance */
634                         call = alloc_call();
635                         /* new state */
636                         call->state = CHAN_LCR_STATE_IN_PREPARE;
637                         /* set ref */
638                         call->ref = ref;
639                         /* wait for setup (or release from asterisk) */
640                 } else
641                 {
642                         /* new ref, as requested from this remote application */
643                         call = find_call_ref(0);
644                         if (!call)
645                         {
646                                 /* send release, if ref does not exist */
647                                 newparam.disconnectinfo.cause = CAUSE_NORMAL;
648                                 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
649                                 send_message(MESSAGE_RELEASE, ref, &newparam);
650                                 return(0);
651                         }
652                         /* store new ref */
653                         call->ref = ref;
654                         /* send pending setup info */
655                         if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
656                                 send_setup_to_lcr(call);
657                         /* release if asterisk has signed off */
658                         else if (call->state == CHAN_LCR_STATE_RELEASE)
659                         {
660                                 /* send release */
661                                 newparam.disconnectinfo.cause = todo
662                                 newparam.disconnectinfo.location = todo
663                                 send_message(MESSAGE_RELEASE, ref, &newparam);
664                                 /* free call */
665                                 free_call(call);
666                                 return(0);
667                         }
668                 }
669                 return(0);
670         }
671
672         /* check ref */
673         if (!ref)
674         {
675                 fprintf(stderr, "received message %d without ref\n", message_type);
676                 return(-1);
677         }
678         call = find_call_ref(ref);
679         if (!call)
680         {
681                 /* ignore ref that is not used (anymore) */
682                 return(0);
683         }
684
685         /* handle messages */
686         switch(message_type)
687         {
688                 case MESSAGE_SETUP:
689                 lcr_in_setup(call, message_type, param);
690                 break;
691
692                 case MESSAGE_OVERLAP:
693                 lcr_in_overlap(call, message_type, param);
694                 break;
695
696                 case MESSAGE_PROCEEDING:
697                 lcr_in_proceeding(call, message_type, param);
698                 break;
699
700                 case MESSAGE_ALERTING:
701                 lcr_in_alerting(call, message_type, param);
702                 break;
703
704                 case MESSAGE_CONNECT:
705                 lcr_in_connect(call, message_type, param);
706                 break;
707
708                 case MESSAGE_DISCONNECT:
709                 lcr_in_disconnect(call, message_type, param);
710                 break;
711
712                 case MESSAGE_RELEASE:
713                 lcr_in_release(call, message_type, param);
714                 break;
715
716                 case MESSAGE_INFORMATION:
717                 lcr_in_disconnect(call, message_type, param);
718                 break;
719
720                 case MESSAGE_NOTIFY:
721                 lcr_in_notify(call, message_type, param);
722                 break;
723
724                 case MESSAGE_FACILITY:
725                 lcr_in_facility(call, message_type, param);
726                 break;
727
728                 case MESSAGE_PATTERN:
729 #warning todo
730                 break;
731
732                 case MESSAGE_NOPATTERN:
733 #warning todo
734                 break;
735
736                 case MESSAGE_AUDIOPATH:
737 #warning todo
738                 break;
739
740                 default:
741 #warning unhandled
742         }
743         return(0);
744 }
745
746
747 /* asterisk handler
748  * warning! not thread safe
749  * returns -1 for socket error, 0 for no work, 1 for work
750  */
751 int handle_socket(void)
752 {
753         int work = 0;
754         int len;
755         struct admin_message msg;
756         struct admin_list *admin;
757
758         int sock;
759
760         #warning SOCKET FEHLT!
761         /* read from socket */
762         len = read(sock, &msg, sizeof(msg));
763         if (len == 0)
764         {
765                 printf("Socket closed\n");
766                 return(-1); // socket closed
767         }
768         if (len > 0)
769         {
770                 if (len != sizeof(msg))
771                 {
772                         fprintf(stderr, "Socket short read (%d)\n", len);
773                         return(-1); // socket error
774                 }
775                 if (msg.message != ADMIN_MESSAGE)
776                 {
777                         fprintf(stderr, "Socket received illegal message %d\n", msg.message);
778                         return(-1); // socket error
779                 }
780                 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
781                 printf("message received %d\n", msg.u.msg.type);
782                 work = 1;
783         } else
784         {
785                 if (errno != EWOULDBLOCK)
786                 {
787                         fprintf(stderr, "Socket error %d\n", errno);
788                         return(-1);
789                 }
790         }
791
792         /* write to socket */
793         if (!admin_first)
794                 return(work);
795         admin = admin_first;
796         len = write(sock, &admin->msg, sizeof(msg));
797         if (len == 0)
798         {
799                 printf("Socket closed\n");
800                 return(-1); // socket closed
801         }
802         if (len > 0)
803         {
804                 if (len != sizeof(msg))
805                 {
806                         fprintf(stderr, "Socket short write (%d)\n", len);
807                         return(-1); // socket error
808                 }
809                 /* free head */
810                 admin_first = admin->next;
811                 free(admin);
812
813                 work = 1;
814         } else
815         {
816                 if (errno != EWOULDBLOCK)
817                 {
818                         fprintf(stderr, "Socket error %d\n", errno);
819                         return(-1);
820                 }
821         }
822
823         return(work);
824 }
825
826 /*
827  * open and close socket
828  */
829 int open_socket(void)
830 {
831         int ret;
832         int sock;
833         char *socket_name = SOCKET_NAME;
834         int conn;
835         struct sockaddr_un sock_address;
836         unsigned long on = 1;
837         union parameter param;
838
839         /* open socket */
840         if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
841         {
842                 ast_log(LOG_ERROR, "Failed to create socket.\n");
843                 return(sock);
844         }
845
846         /* set socket address and name */
847         memset(&sock_address, 0, sizeof(sock_address));
848         sock_address.sun_family = PF_UNIX;
849         strcpy(sock_address.sun_path, socket_name);
850
851         /* connect socket */
852         if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
853         {
854                 close(sock);
855                 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
856                 return(conn);
857         }
858
859         /* set non-blocking io */
860         if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
861         {
862                 close(sock);
863                 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
864                 return(ret);
865         }
866
867         /* enque hello message */
868         memset(&param, 0, sizeof(param));
869         strcpy(param.hello.application, "asterisk");
870         send_message(MESSAGE_HELLO, 0, &param);
871
872         return(sock);
873 }
874
875 void close_socket(int sock)
876 {
877         /* close socket */
878         if (socket >= 0)        
879                 close(sock);
880 }
881
882
883 socket muss per timer fuer das Ã¶ffnen checken
884 static void *chan_thread(void *arg)
885 {
886         int work;
887
888         pthread_mutex_lock(&chan_lock);
889
890         while(!quit)
891         {
892                 work = 0;
893
894                 /* handle socket */
895                 int ret = handle_socket();
896                 if (ret < 0)
897                         break;
898                 if (ret)
899                         work = 1;
900
901                 /* handle mISDN */
902                 ret = bchannel_handle();
903                 if (ret)
904                         work = 1;
905                 
906                 if (!work)
907                 {
908                         pthread_mutex_unlock(&chan_lock);
909                         usleep(30000);
910                         pthread_mutex_lock(&chan_lock);
911                 }
912         }
913         
914         pthread_mutex_unlock(&chan_lock);
915
916         return NULL;
917 }
918
919 /*
920  * send setup info to LCR
921  * this function is called, when asterisk call is received and ref is received
922  */
923 static void send_setup_to_lcr(struct chan_call *call)
924 {
925         union parameter newparam;
926
927         if (!ast || !call->ref)
928                 return;
929
930         /* send setup message to LCR */
931         memset(&newparam, 0, sizeof(union parameter));
932         newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;      
933         newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;   
934         if (ast->cid->cid_num) if (ast->cid->cid_num[0])
935                 strncpy(newparam.setup.callerinfo.id, ast->cid->cid_num, sizeof(newparam.setup.callerinfo.id)-1);
936         if (ast->cid->cid_name) if (ast->cid->cid_name[0])
937                 strncpy(newparam.setup.callerinfo.name, ast->cid->cid_name, sizeof(newparam.setup.callerinfo.name)-1);
938         if (ast->cid->cid_rdnis) if (ast->cid->cid_rdnis[0])
939         {
940                 strncpy(newparam.setup.redirinfo.id, ast->cid->cid_rdnis, sizeof(newparam.setup.redirinfo.id)-1);
941                 newparam.setup.redirinfo.itype = INFO_ITYPE_CHAN;       
942                 newparam.setup.redirinfo.ntype = INFO_NTYPE_UNKNOWN;    
943         }
944         switch(ast->cid->cid_pres & AST_PRES_RESTRICTION)
945         {
946                 case AST_PRES_ALLOWED:
947                 newparam.setup.callerinfo.present = INFO_PRESENT_ALLOWED;
948                 break;
949                 case AST_PRES_RESTRICTED:
950                 newparam.setup.callerinfo.present = INFO_PRESENT_RESTRICTED;
951                 break;
952                 case AST_PRES_UNAVAILABLE:
953                 newparam.setup.callerinfo.present = INFO_PRESENT_NOTAVAIL;
954                 break;
955                 default:
956                 newparam.setup.callerinfo.present = INFO_PRESENT_NULL;
957         }
958         switch(ast->cid->cid_ton)
959         {
960                 case AST_wasist:
961                 newparam.setup.callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
962                 break;
963                 case AST_wasist:
964                 newparam.setup.callerinfo.ntype = INFO_NTYPE_NATIONAL;
965                 break;
966                 case AST_wasist:
967                 newparam.setup.callerinfo.ntype = INFO_NTYPE_INTERNATIONAL;
968                 break;
969         }
970         newparam.setup.capainfo.bearer_capa = ast->transfercapability;
971         newparam.setup.capainfo.bearer_user = alaw 3, ulaw 2;
972         newparam.setup.capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
973         newparam.setup.capainfo.hlc = INFO_HLC_NONE;
974         newparam.setup.capainfo.exthlc = INFO_HLC_NONE;
975         send_message(MESSAGE_SETUP, call->ref, &newparam);
976
977         /* change to outgoing setup state */
978         call->state = CHAN_LCR_STATE_OUT_SETUP;
979 }
980
981 #if 0
982 CHRISTIAN: das war ein konflikt beim pullen
983 siehe anderes lcr_request();
984 bedenke: das ast_log muss noch Ã¼eberall eingepflegt werden
985
986 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
987 {
988         struct chan_call *call=alloc_call();
989
990         if (call) {
991 #warning hier muss jetzt wohl eine Ref angefordert werden!
992                 ast=lcr_ast_new(call, ext, NULL, 0 );
993
994                 if (ast) {
995                         call->ast=ast;
996                 } else {
997                         ast_log(LOG_WARNING, "Could not create new Asterisk Channel\n");
998                         free_call(call);
999                 }
1000         } else {
1001                 ast_log(LOG_WARNING, "Could not create new Lcr Call Handle\n");
1002         }
1003
1004         return ast;
1005 }
1006
1007         struct ast_channel *ast=NULL;
1008
1009         char buf[128];
1010         char *port_str, *ext, *p;
1011         int port;
1012
1013         ast_copy_string(buf, data, sizeof(buf)-1);
1014         p=buf;
1015         port_str=strsep(&p, "/");
1016         ext=strsep(&p, "/");
1017         ast_verbose("portstr:%s ext:%s\n",port_str, ext);
1018
1019         sprintf(buf,"%s/%s",lcr_type,(char*)data);
1020 #endif
1021
1022 /*
1023  * send dialing info to LCR
1024  * this function is called, when setup acknowledge is received and dialing
1025  * info is available.
1026  */
1027 static void send_dialque_to_lcr(struct chan_call *call)
1028 {
1029         union parameter newparam;
1030
1031         if (!ast || !call->ref || !call->dialque)
1032                 return;
1033         
1034         /* send setup message to LCR */
1035         memset(&newparam, 0, sizeof(union parameter));
1036         strncpy(newparam.dialinginfo.id, call->dialque, sizeof(newparam.dialinginfo.id)-1);
1037         call->dialque[0] = '\0';
1038         send_message(MESSAGE_INFORMATION, call->ref, &newparam);
1039 }
1040
1041 /*
1042  * new asterisk instance
1043  */
1044 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
1045 {
1046         union parameter newparam;
1047
1048         pthread_mutex_lock(&chan_lock);
1049
1050         /* create call instance */
1051         call = alloc_call();
1052         if (!call)
1053         {
1054                 /* failed to create instance */
1055                 return NULL;
1056         }
1057         /* create asterisk channel instrance */
1058         ast = ast_channel_alloc(1);
1059         if (!ast)
1060         {
1061                 free_call(call);
1062                 /* failed to create instance */
1063                 return NULL;
1064         }
1065         /* link together */
1066         ast->tech_pvt = call;
1067         call->ast = ast;
1068         ast->tech = &lcr_tech;
1069         /* configure channel */
1070         ast->state = AST_STATE_RESERVED;
1071         snprintf(ast->name, sizeof(ast->name), "%s/%d", lcr_type, ++glob_channel);
1072         ast->name[sizeof(ast->name)-1] = '\0';
1073         ast->type = lcr_type;
1074         ast->nativeformat = configfile->lawformat;
1075         ast->readformat = ast->rawreadformat = configfile->lawformat;
1076         ast->writeformat = ast->rawwriteformat = configfile->lawformat;
1077         ast->hangupcause = 0;
1078         /* send MESSAGE_NEWREF */
1079         memset(&newparam, 0, sizeof(union parameter));
1080         newparam.direction = 0; /* request from app */
1081         send_message(MESSAGE_NEWREF, 0, &newparam);
1082         /* set state */
1083         call->state = CHAN_LCR_STATE_OUT_PREPARE;
1084
1085         pthread_mutex_unlock(&chan_lock);
1086 }
1087
1088 /*
1089  * call from asterisk
1090  */
1091 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
1092 {
1093         union parameter newparam;
1094         struct chan_call *call=ast->tech_pvt;
1095         char buf[128];
1096         char *port_str, *dad, *p;
1097
1098         if (!call) return -1;
1099
1100         pthread_mutex_lock(&chan_lock);
1101
1102         hier muss noch
1103         ast_copy_string(buf, dest, sizeof(buf)-1);
1104         p=buf;
1105         port_str=strsep(&p, "/");
1106         dad=strsep(&p, "/");
1107
1108         /* send setup message, if we already have a callref */
1109         if (call->ref)
1110                 send_setup_to_lcr(call);
1111
1112         if (lcr_debug)
1113                 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
1114
1115 #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.
1116         
1117         pthread_mutex_unlock(&chan_lock);
1118         return 0; 
1119 }
1120
1121 static int lcr_digit(struct ast_channel *ast, char digit)
1122 {
1123         union parameter newparam;
1124         char buf[]="x";
1125
1126         if (!call) return -1;
1127
1128         /* only pass IA5 number space */
1129         if (digit > 126 || digit < 32)
1130                 return 0;
1131
1132         pthread_mutex_lock(&chan_lock);
1133
1134         /* send information or queue them */
1135         if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
1136         {
1137                 memset(&newparam, 0, sizeof(union parameter));
1138                 newparam.dialinginfo.id[0] = digit;
1139                 newparam.dialinginfo.id[1] = '\0';
1140                 send_message(MESSAGE_INFORMATION, call->ref, &newparam);
1141         } else
1142         if (!call->ref
1143          && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
1144         {
1145                 *buf = digit;
1146                 strncat(call->dialque, buf, strlen(char->dialque)-1);
1147         }
1148
1149         pthread_mutex_unlock(&chan_lock);
1150         
1151         return(0);
1152 }
1153
1154 static int lcr_answer(struct ast_channel *c)
1155 {
1156         union parameter newparam;
1157         struct chan_call *call=c->tech_pvt;
1158         
1159         if (!call) return -1;
1160
1161         pthread_mutex_lock(&chan_lock);
1162
1163         /* check bridged connectinfo */
1164         if (call->bchannel)
1165                 if (call->bchannel->bridge_channel)
1166                         if (call->bchannel->bridge_channel->call)
1167                         {
1168                                 memcpy(call->connectinfo, call->bchannel->bridge_channel->call->connectinfo, sizeof(struct connect_info));
1169                         }
1170         /* send connect message to lcr */
1171         memset(&newparam, 0, sizeof(union parameter));
1172         memcpy(param->connectinfo, call->connectinfo, sizeof(struct connect_info));
1173         send_message(MESSAGE_CONNECT, call->ref, &newparam);
1174         /* change state */
1175         call->state = CHAN_LCR_STATE_CONNECT;
1176         
1177         pthread_mutex_unlock(&chan_lock);
1178         return 0;
1179 }
1180
1181 static int lcr_hangup(struct ast_channel *ast)
1182 {
1183         union parameter newparam;
1184         struct chan_call *call = ast->tech_pvt;
1185
1186         if (!call)
1187                 return 0;
1188
1189         pthread_mutex_lock(&chan_lock);
1190         /* disconnect asterisk, maybe not required */
1191         ast->tech_pvt = NULL;
1192         if (call->ref)
1193         {
1194                 /* release */
1195                 memset(&newparam, 0, sizeof(union parameter));
1196                 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
1197                 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1198                 send_message(MESSAGE_RELEASE, call->ref, &newparam);
1199                 /* remove call */
1200                 free_call(call);
1201                 pthread_mutex_unlock(&chan_lock);
1202                 return 0;
1203         } else
1204         {
1205                 /* ref is not set, due to prepare setup or release */
1206                 if (call->state == CHAN_LCR_STATE_RELEASE)
1207                 {
1208                         /* we get the response to our release */
1209                         free_call(call);
1210                 } else
1211                 {
1212                         /* during prepare, we change to release state */
1213                         call->state = CHAN_LCR_STATE_RELEASE;
1214                 }
1215         } 
1216         pthread_mutex_unlock(&chan_lock);
1217         return 0;
1218 }
1219
1220 static int lcr_write(struct ast_channel *ast, struct ast_frame *f)
1221 {
1222         struct chan_call *call= ast->tech_pvt;
1223         if (!call) return 0;
1224         pthread_mutex_lock(&chan_lock);
1225         pthread_mutex_unlock(&chan_lock);
1226 }
1227
1228
1229 static struct ast_frame *lcr_read(struct ast_channel *ast)
1230 {
1231         struct chan_call *call = ast->tech_pvt;
1232         if (!call) return 0;
1233         pthread_mutex_lock(&chan_lock);
1234         pthread_mutex_unlock(&chan_lock);
1235 }
1236
1237 static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, size_t datalen)
1238 {
1239         union parameter newparam;
1240         int res = -1;
1241
1242         if (!call) return -1;
1243
1244         pthread_mutex_lock(&chan_lock);
1245
1246         switch (cond) {
1247                 case AST_CONTROL_BUSY:
1248                         /* send message to lcr */
1249                         memset(&newparam, 0, sizeof(union parameter));
1250                         newparam.disconnectinfo.cause = 17;
1251                         newparam.disconnectinfo.location = 5;
1252                         send_message(MESSAGE_DISCONNECT, call->ref, &newparam);
1253                         /* change state */
1254                         call->state = CHAN_LCR_STATE_OUT_DISCONNECT;
1255                         /* return */
1256                         pthread_mutex_unlock(&chan_lock);
1257                         return 0;
1258                 case AST_CONTROL_CONGESTION:
1259                         /* return */
1260                         pthread_mutex_unlock(&chan_lock);
1261                         return -1;
1262                 case AST_CONTROL_RINGING:
1263                         /* send message to lcr */
1264                         memset(&newparam, 0, sizeof(union parameter));
1265                         send_message(MESSAGE_ALERTING, call->ref, &newparam);
1266                         /* change state */
1267                         call->state = CHAN_LCR_STATE_OUT_ALERTING;
1268                         /* return */
1269                         pthread_mutex_unlock(&chan_lock);
1270                         return 0;
1271                 case -1:
1272                         /* return */
1273                         pthread_mutex_unlock(&chan_lock);
1274                         return 0;
1275
1276                 case AST_CONTROL_VIDUPDATE:
1277                         res = -1;
1278                         break;
1279                 case AST_CONTROL_HOLD:
1280                         /* send message to lcr */
1281                         memset(&newparam, 0, sizeof(union parameter));
1282                         newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
1283                         send_message(MESSAGE_NOTIFY, call->ref, &newparam);
1284                         break;
1285                 case AST_CONTROL_UNHOLD:
1286                         /* send message to lcr */
1287                         memset(&newparam, 0, sizeof(union parameter));
1288                         newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
1289                         send_message(MESSAGE_NOTIFY, call->ref, &newparam);
1290                         break;
1291
1292                 default:
1293                         ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
1294                         /* return */
1295                         pthread_mutex_unlock(&chan_lock);
1296                         return -1;
1297         }
1298
1299         /* return */
1300         pthread_mutex_unlock(&chan_lock);
1301         return 0;
1302 }
1303
1304 static struct ast_channel_tech lcr_tech = {
1305         .type=lcr_type,
1306         .description="Channel driver for connecting to Linux-Call-Router",
1307         .capabilities=AST_FORMAT_ALAW,
1308         .requester=lcr_request,
1309         .send_digit=lcr_digit,
1310         .call=lcr_call,
1311         .bridge=lcr_bridge, 
1312         .hangup=lcr_hangup,
1313         .answer=lcr_answer,
1314         .read=lcr_read,
1315         .write=lcr_write,
1316         .indicate=lcr_indicate,
1317 //      .fixup=lcr_fixup,
1318 //      .send_text=lcr_send_text,
1319         .properties=0
1320 };
1321
1322 #warning das muss mal aus der config datei gelesen werden:
1323 char lcr_context[]="from-lcr";
1324
1325
1326 TODO: muss oben ins lcr_in setup und ins lcr_request
1327 static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref)
1328 {
1329         struct ast_channel *tmp;
1330         char *cid_name = 0, *cid_num = 0;
1331
1332
1333         if (callerid)
1334                 ast_callerid_parse(callerid, &cid_name, &cid_num);
1335
1336         tmp = ast_channel_alloc(1, AST_STATE_RESERVED, cid_num, cid_name, "", exten, "", 0, "%s/%d", lcr_type,  ref);
1337
1338         if (tmp) {
1339                 tmp->tech = &lcr_tech;
1340                 tmp->writeformat = AST_FORMAT_ALAW;
1341                 tmp->readformat = AST_FORMAT_ALAW;
1342
1343                 ast_copy_string(tmp->context, lcr_context, AST_MAX_CONTEXT);
1344
1345         }
1346
1347         return tmp;
1348 }
1349
1350
1351
1352 /*
1353  * cli
1354  */
1355 static int lcr_show_lcr (int fd, int argc, char *argv[])
1356 {
1357 }
1358
1359 static int lcr_show_calls (int fd, int argc, char *argv[])
1360 {
1361 }
1362
1363 static int lcr_reload_routing (int fd, int argc, char *argv[])
1364 {
1365 }
1366
1367 static int lcr_reload_interfaces (int fd, int argc, char *argv[])
1368 {
1369 }
1370
1371 static int lcr_port_block (int fd, int argc, char *argv[])
1372 {
1373 }
1374
1375 static int lcr_port_unblock (int fd, int argc, char *argv[])
1376 {
1377 }
1378
1379 static int lcr_port_unload (int fd, int argc, char *argv[])
1380 {
1381 }
1382
1383 static struct ast_cli_entry cli_show_lcr =
1384 { {"lcr", "show", "lcr", NULL},
1385  lcr_show_lcr,
1386  "Shows current states of LCR core",
1387  "Usage: lcr show lcr\n",
1388 };
1389
1390 static struct ast_cli_entry cli_show_calls =
1391 { {"lcr", "show", "calls", NULL},
1392  lcr_show_calls,
1393  "Shows current calls made by LCR and Asterisk",
1394  "Usage: lcr show calls\n",
1395 };
1396
1397 static struct ast_cli_entry cli_reload_routing =
1398 { {"lcr", "reload", "routing", NULL},
1399  lcr_reload_routing,
1400  "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
1401  "Usage: lcr reload routing\n",
1402 };
1403
1404 static struct ast_cli_entry cli_reload_interfaces =
1405 { {"lcr", "reload", "interfaces", NULL},
1406  lcr_reload_interfaces,
1407  "Reloads interfaces conf of LCR",
1408  "Usage: lcr reload interfaces\n",
1409 };
1410
1411 static struct ast_cli_entry cli_port_block =
1412 { {"lcr", "port", "block", NULL},
1413  lcr_port_block,
1414  "Blocks LCR port for further calls",
1415  "Usage: lcr port block \"<port>\"\n",
1416 };
1417
1418 static struct ast_cli_entry cli_port_unblock =
1419 { {"lcr", "port", "unblock", NULL},
1420  lcr_port_unblock,
1421  "Unblocks or loads LCR port, port is opened my mISDN",
1422  "Usage: lcr port unblock \"<port>\"\n",
1423 };
1424
1425 static struct ast_cli_entry cli_port_unload =
1426 { {"lcr", "port", "unload", NULL},
1427  lcr_port_unload,
1428  "Unloads LCR port, port is closes by mISDN",
1429  "Usage: lcr port unload \"<port>\"\n",
1430 };
1431
1432
1433 /*
1434  * module loading and destruction
1435  */
1436 int load_module(void)
1437 {
1438 //      ast_mutex_init(&release_lock);
1439
1440 //      lcr_cfg_update_ptp();
1441
1442         pthread_mutex_init(&chan_lock, NULL);
1443         
1444         if (!(lcr_sock = open_socket())) {
1445                 ast_log(LOG_ERROR, "Unable to connect\n");
1446                 lcr_sock = -1;
1447                 /* continue with closed socket */
1448         }
1449
1450         if (!bchannel_initialize()) {
1451                 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
1452                 close_socket(lcr_sock);
1453                 return -1;
1454         }
1455         mISDN_created = 1;
1456
1457         if (ast_channel_register(&lcr_tech)) {
1458                 ast_log(LOG_ERROR, "Unable to register channel class\n");
1459                 bchannel_deinitialize();
1460                 close_socket(lcr_sock);
1461                 return -1;
1462         }
1463  
1464 #if 0   
1465         ast_cli_register(&cli_show_lcr);
1466         ast_cli_register(&cli_show_calls);
1467
1468         ast_cli_register(&cli_reload_routing);
1469         ast_cli_register(&cli_reload_interfaces);
1470         ast_cli_register(&cli_port_block);
1471         ast_cli_register(&cli_port_unblock);
1472         ast_cli_register(&cli_port_unload);
1473   
1474         ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
1475                                  "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
1476                                  "Sets mISDN opts. and optargs\n"
1477                                  "\n"
1478                                  "The available options are:\n"
1479                                  "    d - Send display text on called phone, text is the optparam\n"
1480                                  "    n - don't detect dtmf tones on called channel\n"
1481                                  "    h - make digital outgoing call\n" 
1482                                  "    c - make crypted outgoing call, param is keyindex\n"
1483                                  "    e - perform echo cancelation on this channel,\n"
1484                                  "        takes taps as arguments (32,64,128,256)\n"
1485                                  "    s - send Non Inband DTMF as inband\n"
1486                                  "   vr - rxgain control\n"
1487                                  "   vt - txgain control\n"
1488                 );
1489
1490         
1491         lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1492
1493         chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
1494 =======
1495         //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1496 #endif
1497
1498         quit = 1;       
1499         if ((pthread_create(&chan_tid, NULL, chan_thread, arg)<0))
1500         {
1501                 failed to create thread
1502                 bchannel_deinitialize();
1503                 close_socket(lcr_sock);
1504                 ast_channel_unregister(&lcr_tech);
1505                 return -1;
1506         }
1507         return 0;
1508 }
1509
1510 int unload_module(void)
1511 {
1512         /* First, take us out of the channel loop */
1513         ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
1514
1515         quit = 1;
1516         pthread_join(chan_tid, NULL);   
1517         
1518         ast_channel_unregister(&lcr_tech);
1519
1520         if (mISDN_created) {
1521                 bchannel_deinitialize();
1522                 mISDN_created = 0;
1523         }
1524
1525         if (lcr_sock >= 0) {
1526                 close(lcr_sock);
1527                 lcr_sock = -1;
1528         }
1529
1530         return 0;
1531 }
1532
1533 static int reload_module(void)
1534 {
1535 //      reload_config();
1536         return 0;
1537 }
1538
1539
1540 ast_mutex_t usecnt_lock;
1541 int usecnt;
1542
1543 int usecount(void)
1544 {
1545         int res;
1546         ast_mutex_lock(&usecnt_lock);
1547         res = usecnt;
1548         ast_mutex_unlock(&usecnt_lock);
1549         return res;
1550 }
1551
1552
1553 char *desc="Channel driver for lcr";
1554
1555 char *description(void)
1556 {
1557         return desc;
1558 }
1559
1560 char *key(void)
1561 {
1562         return ASTERISK_GPL_KEY;
1563 }
1564
1565 #define AST_MODULE "chan_lcr"
1566 AST_MODULE_INFO(ASTERISK_GPL_KEY,
1567                                 AST_MODFLAG_DEFAULT,
1568                                 "Channel driver for LCR",
1569                                 .load = load_module,
1570                                 .unload = unload_module,
1571                                 .reload = reload_module,
1572                            );
1573