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