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