1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** Asterisk socket client **
10 \*****************************************************************************/
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.
21 Call is initiated by LCR:
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.
32 Call is initiated by Asterisk:
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.
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.
55 Call is released by LCR:
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".
69 Call is released by Asterisk:
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".
82 #warning reconnect after socket closed, release all calls.
83 #warning debug of call handling
84 #warning ausloesen beim socket-verlust
92 #include <sys/types.h>
96 #include <sys/ioctl.h>
97 #include <sys/socket.h>
101 #include <semaphore.h>
103 pthread_mutex_t chan_lock;
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>
125 #include "extension.h"
127 #include "lcrsocket.h"
129 #include "bchannel.h"
130 #include "chan_lcr.h"
131 #include "callerid.h"
133 CHAN_LCR_STATE // state description structure
138 char lcr_type[]="lcr";
143 int glob_channel = 0;
148 struct admin_list *next;
149 struct admin_msg msg;
150 } *admin_first = NULL;
152 static struct ast_channel_tech lcr_tech;
155 * channel and call instances
157 struct chan_call *call_first;
159 struct chan_call *find_call_ref(unsigned long ref)
161 struct chan_call *call = call_first;
165 if (call->ref == ref)
173 struct chan_call *find_call_handle(unsigned long handle)
175 struct chan_call *call = call_first;
179 if (call->bchannel_handle == handle)
187 struct chan_call *alloc_call(void)
189 struct chan_call **callp = &call_first;
192 callp = &((*callp)->next);
194 *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
196 memset(*callp, 0, sizeof(struct chan_call));
200 void free_call(struct chan_call *call)
202 struct chan_call **temp = &call_first;
208 *temp = (*temp)->next;
211 if (call->channel->call)
212 call->channel->call = NULL;
217 temp = &((*temp)->next);
221 unsigned short new_brige_id(void)
223 struct bchannel *channel;
224 unsigned short id = 1;
226 /* search for lowest bridge id that is not in use and not 0 */
229 channel = bchannel_first;
232 if (channel->bridge_id == id)
234 channel = channel->next;
245 * receive bchannel data
247 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
251 void rx_dtmf(struct bchannel *bchannel, char tone)
256 * enque message to LCR
258 int send_message(int message_type, unsigned long ref, union parameter *param)
260 struct admin_list *admin, **adminp;
262 adminp = &admin_first;
264 adminp = &((*adminp)->next);
265 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
268 admin->msg.type = message_type;
269 admin->msg.ref = ref;
270 memcpy(&admin->msg.param, param, sizeof(union parameter));
276 * send setup info to LCR
277 * this function is called, when asterisk call is received and ref is received
279 static void send_setup_to_lcr(struct chan_call *call)
281 union parameter newparam;
283 if (!call->ast || !call->ref)
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])
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;
300 switch(call->ast->cid.cid_pres & AST_PRES_RESTRICTION)
302 case AST_PRES_ALLOWED:
303 newparam.setup.callerinfo.present = INFO_PRESENT_ALLOWED;
305 case AST_PRES_RESTRICTED:
306 newparam.setup.callerinfo.present = INFO_PRESENT_RESTRICTED;
308 case AST_PRES_UNAVAILABLE:
309 newparam.setup.callerinfo.present = INFO_PRESENT_NOTAVAIL;
312 newparam.setup.callerinfo.present = INFO_PRESENT_NULL;
314 switch(call->ast->cid.cid_ton)
317 newparam.setup.callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
320 newparam.setup.callerinfo.ntype = INFO_NTYPE_NATIONAL;
323 newparam.setup.callerinfo.ntype = INFO_NTYPE_INTERNATIONAL;
326 newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
328 newparam.setup.capainfo.bearer_capa = call->ast->transfercapability;
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);
336 /* change to outgoing setup state */
337 call->state = CHAN_LCR_STATE_OUT_SETUP;
341 * send dialing info to LCR
342 * this function is called, when setup acknowledge is received and dialing
345 static void send_dialque_to_lcr(struct chan_call *call)
347 union parameter newparam;
349 if (!call->ast || !call->ref || !call->dialque)
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);
360 * in case of a bridge, the unsupported message can be forwarded directly
361 * to the remote call.
363 static void bridge_message_if_bridged(struct chan_call *call, int message_type, union parameter *param)
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);
375 * incoming setup from LCR
377 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
379 struct ast_channel *ast;
380 union parameter newparam;
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);
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);
396 /* set ast pointer */
398 ast->tech_pvt = call;
399 ast->tech = &lcr_tech;
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);
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));
413 switch (param->setup.callerinfo.present)
415 case INFO_PRESENT_ALLOWED:
416 ast->cid.cid_pres = AST_PRES_ALLOWED;
418 case INFO_PRESENT_RESTRICTED:
419 ast->cid.cid_pres = AST_PRES_RESTRICTED;
422 ast->cid.cid_pres = AST_PRES_UNAVAILABLE;
424 switch (param->setup.callerinfo.ntype)
426 case INFO_NTYPE_SUBSCRIBER:
427 ast->cid.cid_ton = 4;
429 case INFO_NTYPE_NATIONAL:
430 ast->cid.cid_ton = 2;
432 case INFO_NTYPE_INTERNATIONAL:
433 ast->cid.cid_ton = 1;
436 ast->cid.cid_ton = 0;
438 ast->transfercapability = param->setup.capainfo.bearer_capa;
440 /* configure channel */
443 ast->nativeformat = configfile->lawformat;
444 ast->readformat = ast->rawreadformat = configfile->lawformat;
445 ast->writeformat = ast->rawwriteformat = configfile->lawformat;
447 ast->hangupcause = 0;
450 call->state = CHAN_LCR_STATE_IN_SETUP;
452 /* send setup to asterisk */
455 /* send setup acknowledge to lcr */
456 memset(&newparam, 0, sizeof(union parameter));
457 send_message(MESSAGE_OVERLAP, call->ref, &newparam);
460 call->state = CHAN_LCR_STATE_IN_DIALING;
464 * incoming setup acknowledge from LCR
466 static void lcr_in_overlap(struct chan_call *call, int message_type, union parameter *param)
468 if (!call->ast) return;
470 /* send pending digits in dialque */
472 send_dialque_to_lcr(call);
473 /* change to overlap state */
474 call->state = CHAN_LCR_STATE_OUT_DIALING;
478 * incoming proceeding from LCR
480 static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
483 call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
484 /* send event to asterisk */
486 ast_queue_control(call->ast, AST_CONTROL_PROCEEDING);
490 * incoming alerting from LCR
492 static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
495 call->state = CHAN_LCR_STATE_OUT_ALERTING;
496 /* send event to asterisk */
498 ast_queue_control(call->ast, AST_CONTROL_RINGING);
502 * incoming connect from LCR
504 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
507 call->state = CHAN_LCR_STATE_CONNECT;
508 /* copy connectinfo */
509 memcpy(&call->connectinfo, ¶m->connectinfo, sizeof(struct connect_info));
510 /* send event to asterisk */
512 ast_queue_control(call->ast, AST_CONTROL_ANSWER);
516 * incoming disconnect from LCR
518 static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param)
520 union parameter newparam;
523 call->state = CHAN_LCR_STATE_IN_DISCONNECT;
525 call->cause = param->disconnectinfo.cause;
526 call->location = param->disconnectinfo.location;
527 /* if bridge, forward disconnect and return */
529 if (call->channel->bridge_channel)
530 if (call->channel->bridge_channel->call)
532 bridge_message_if_bridged(call, message_type, param);
536 newparam.disconnectinfo.cause = CAUSE_NORMAL;
537 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
538 send_message(MESSAGE_RELEASE, call->ref, &newparam);
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;
548 * incoming setup acknowledge from LCR
550 static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param)
554 /* change to release state */
555 call->state = CHAN_LCR_STATE_RELEASE;
556 /* copy release info */
559 call->cause = param->disconnectinfo.cause;
560 call->location = param->disconnectinfo.location;
562 /* if we have an asterisk instance, send hangup, else we are done */
565 call->ast->hangupcause = call->cause;
566 ast_queue_hangup(call->ast);
575 * incoming information from LCR
577 static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param)
582 if (!call->ast) return;
585 p = param->information.id;
586 if (call->state == CHAN_LCR_STATE_IN_DIALING && *p)
590 /* send digit to asterisk */
591 memset(&fr, 0, sizeof(fr));
592 fr.frametype = AST_FRAME_DTMF;
594 fr.delivery = ast_tv(0, 0);
595 ast_queue_frame(call->ast, &fr);
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);
605 * incoming information from LCR
607 static void lcr_in_notify(struct chan_call *call, int message_type, union parameter *param)
609 if (!call->ast) return;
611 /* use bridge to forware message not supported by asterisk */
612 bridge_message_if_bridged(call, message_type, param);
616 * incoming information from LCR
618 static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
620 if (!call->ast) return;
622 /* use bridge to forware message not supported by asterisk */
623 bridge_message_if_bridged(call, message_type, param);
627 * message received from LCR
629 int receive_message(int message_type, unsigned long ref, union parameter *param)
631 union parameter newparam;
632 struct bchannel *bchannel;
633 struct chan_call *call;
635 memset(&newparam, 0, sizeof(union parameter));
637 /* handle bchannel message*/
638 if (message_type == MESSAGE_BCHANNEL)
640 switch(param->bchannel.type)
642 case BCHANNEL_ASSIGN:
643 if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
645 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
648 /* create bchannel */
649 bchannel = alloc_bchannel(param->bchannel.handle);
652 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
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)
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);
666 bchannel->b_txdata = 0;
667 bchannel->b_dtmf = 1;
668 bchannel->b_tx_dejitter = 1;
670 /* in case, ref is not set, this bchannel instance must
671 * be created until it is removed again by LCR */
673 if ((call = find_call_ref(ref)))
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);
681 if (bchannel_create(bchannel))
682 bchannel_activate(bchannel, 1);
685 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
686 newparam.bchannel.handle = param->bchannel.handle;
687 send_message(MESSAGE_BCHANNEL, 0, &newparam);
690 case BCHANNEL_REMOVE:
691 if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
693 #warning alle fprintf nach ast_log
694 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
697 /* unklink from call and destroy bchannel */
698 free_bchannel(bchannel);
701 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
702 newparam.bchannel.handle = param->bchannel.handle;
703 send_message(MESSAGE_BCHANNEL, 0, &newparam);
708 fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
714 if (message_type == MESSAGE_NEWREF)
716 if (param->direction)
718 /* new ref from lcr */
719 if (!ref || find_call_ref(ref))
721 fprintf(stderr, "illegal new ref %ld received\n", ref);
724 /* allocate new call instance */
727 call->state = CHAN_LCR_STATE_IN_PREPARE;
730 /* wait for setup (or release from asterisk) */
733 /* new ref, as requested from this remote application */
734 call = find_call_ref(0);
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);
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)
754 newparam.disconnectinfo.cause = call->cause;
755 newparam.disconnectinfo.location = call->location;
758 newparam.disconnectinfo.cause = 16;
759 newparam.disconnectinfo.location = 5;
761 send_message(MESSAGE_RELEASE, ref, &newparam);
773 fprintf(stderr, "received message %d without ref\n", message_type);
776 call = find_call_ref(ref);
779 /* ignore ref that is not used (anymore) */
783 /* handle messages */
787 lcr_in_setup(call, message_type, param);
790 case MESSAGE_OVERLAP:
791 lcr_in_overlap(call, message_type, param);
794 case MESSAGE_PROCEEDING:
795 lcr_in_proceeding(call, message_type, param);
798 case MESSAGE_ALERTING:
799 lcr_in_alerting(call, message_type, param);
802 case MESSAGE_CONNECT:
803 lcr_in_connect(call, message_type, param);
806 case MESSAGE_DISCONNECT:
807 lcr_in_disconnect(call, message_type, param);
810 case MESSAGE_RELEASE:
811 lcr_in_release(call, message_type, param);
814 case MESSAGE_INFORMATION:
815 lcr_in_disconnect(call, message_type, param);
819 lcr_in_notify(call, message_type, param);
822 case MESSAGE_FACILITY:
823 lcr_in_facility(call, message_type, param);
826 case MESSAGE_PATTERN:
830 case MESSAGE_NOPATTERN:
834 case MESSAGE_AUDIOPATH:
847 * warning! not thread safe
848 * returns -1 for socket error, 0 for no work, 1 for work
850 int handle_socket(void)
854 struct admin_message msg;
855 struct admin_list *admin;
859 #warning SOCKET FEHLT!
860 /* read from socket */
861 len = read(sock, &msg, sizeof(msg));
864 printf("Socket closed\n");
865 return(-1); // socket closed
869 if (len != sizeof(msg))
871 fprintf(stderr, "Socket short read (%d)\n", len);
872 return(-1); // socket error
874 if (msg.message != ADMIN_MESSAGE)
876 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
877 return(-1); // socket error
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);
884 if (errno != EWOULDBLOCK)
886 fprintf(stderr, "Socket error %d\n", errno);
891 /* write to socket */
895 len = write(sock, &admin->msg, sizeof(msg));
898 printf("Socket closed\n");
899 return(-1); // socket closed
903 if (len != sizeof(msg))
905 fprintf(stderr, "Socket short write (%d)\n", len);
906 return(-1); // socket error
909 admin_first = admin->next;
915 if (errno != EWOULDBLOCK)
917 fprintf(stderr, "Socket error %d\n", errno);
926 * open and close socket and thread
928 int open_socket(void)
932 char *socket_name = SOCKET_NAME;
934 struct sockaddr_un sock_address;
935 unsigned long on = 1;
936 union parameter param;
939 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
941 ast_log(LOG_ERROR, "Failed to create socket.\n");
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);
951 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
954 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
958 /* set non-blocking io */
959 if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
962 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
966 /* enque hello message */
967 memset(¶m, 0, sizeof(param));
968 strcpy(param.hello.application, "asterisk");
969 send_message(MESSAGE_HELLO, 0, ¶m);
974 void close_socket(int sock)
981 static void *chan_thread(void *arg)
985 pthread_mutex_lock(&chan_lock);
992 int ret = handle_socket();
999 ret = bchannel_handle();
1005 pthread_mutex_unlock(&chan_lock);
1007 pthread_mutex_lock(&chan_lock);
1011 pthread_mutex_unlock(&chan_lock);
1017 * new asterisk instance
1019 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
1021 union parameter newparam;
1022 struct ast_channel *ast;
1024 pthread_mutex_lock(&chan_lock);
1026 /* create call instance */
1027 call = alloc_call();
1030 /* failed to create instance */
1033 /* create asterisk channel instrance */
1034 ast = ast_channel_alloc(1);
1038 /* failed to create instance */
1042 ast->tech_pvt = call;
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);
1059 call->state = CHAN_LCR_STATE_OUT_PREPARE;
1061 pthread_mutex_unlock(&chan_lock);
1065 * call from asterisk
1067 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
1069 union parameter newparam;
1070 struct chan_call *call=ast->tech_pvt;
1072 char *port_str, *dad, *p;
1074 if (!call) return -1;
1076 pthread_mutex_lock(&chan_lock);
1079 ast_copy_string(buf, dest, sizeof(buf)-1);
1081 port_str=strsep(&p, "/");
1082 dad=strsep(&p, "/");
1084 /* send setup message, if we already have a callref */
1086 send_setup_to_lcr(call);
1089 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
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.
1093 pthread_mutex_unlock(&chan_lock);
1097 static int lcr_digit(struct ast_channel *ast, char digit)
1099 union parameter newparam;
1102 if (!call) return -1;
1104 /* only pass IA5 number space */
1105 if (digit > 126 || digit < 32)
1108 pthread_mutex_lock(&chan_lock);
1110 /* send information or queue them */
1111 if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
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);
1119 && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
1122 strncat(call->dialque, buf, strlen(char->dialque)-1);
1125 pthread_mutex_unlock(&chan_lock);
1130 static int lcr_answer(struct ast_channel *c)
1132 union parameter newparam;
1133 struct chan_call *call=c->tech_pvt;
1135 if (!call) return -1;
1137 pthread_mutex_lock(&chan_lock);
1139 /* check bridged connectinfo */
1141 if (call->bchannel->bridge_channel)
1142 if (call->bchannel->bridge_channel->call)
1144 memcpy(call->connectinfo, call->bchannel->bridge_channel->call->connectinfo, sizeof(struct connect_info));
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);
1151 call->state = CHAN_LCR_STATE_CONNECT;
1153 pthread_mutex_unlock(&chan_lock);
1157 static int lcr_hangup(struct ast_channel *ast)
1159 union parameter newparam;
1160 struct chan_call *call = ast->tech_pvt;
1165 pthread_mutex_lock(&chan_lock);
1166 /* disconnect asterisk, maybe not required */
1167 ast->tech_pvt = NULL;
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);
1177 pthread_mutex_unlock(&chan_lock);
1181 /* ref is not set, due to prepare setup or release */
1182 if (call->state == CHAN_LCR_STATE_RELEASE)
1184 /* we get the response to our release */
1188 /* during prepare, we change to release state */
1189 call->state = CHAN_LCR_STATE_RELEASE;
1192 pthread_mutex_unlock(&chan_lock);
1196 static int lcr_write(struct ast_channel *ast, struct ast_frame *f)
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);
1205 static struct ast_frame *lcr_read(struct ast_channel *ast)
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);
1213 static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, size_t datalen)
1215 union parameter newparam;
1218 if (!call) return -1;
1220 pthread_mutex_lock(&chan_lock);
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);
1230 call->state = CHAN_LCR_STATE_OUT_DISCONNECT;
1232 pthread_mutex_unlock(&chan_lock);
1234 case AST_CONTROL_CONGESTION:
1236 pthread_mutex_unlock(&chan_lock);
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);
1243 call->state = CHAN_LCR_STATE_OUT_ALERTING;
1245 pthread_mutex_unlock(&chan_lock);
1249 pthread_mutex_unlock(&chan_lock);
1252 case AST_CONTROL_VIDUPDATE:
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);
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);
1269 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
1271 pthread_mutex_unlock(&chan_lock);
1276 pthread_mutex_unlock(&chan_lock);
1280 static struct ast_channel_tech lcr_tech = {
1282 .description="Channel driver for connecting to Linux-Call-Router",
1283 .capabilities=AST_FORMAT_ALAW,
1284 .requester=lcr_request,
1285 .send_digit=lcr_digit,
1292 .indicate=lcr_indicate,
1293 // .fixup=lcr_fixup,
1294 // .send_text=lcr_send_text,
1302 static int lcr_show_lcr (int fd, int argc, char *argv[])
1306 static int lcr_show_calls (int fd, int argc, char *argv[])
1310 static int lcr_reload_routing (int fd, int argc, char *argv[])
1314 static int lcr_reload_interfaces (int fd, int argc, char *argv[])
1318 static int lcr_port_block (int fd, int argc, char *argv[])
1322 static int lcr_port_unblock (int fd, int argc, char *argv[])
1326 static int lcr_port_unload (int fd, int argc, char *argv[])
1330 static struct ast_cli_entry cli_show_lcr =
1331 { {"lcr", "show", "lcr", NULL},
1333 "Shows current states of LCR core",
1334 "Usage: lcr show lcr\n",
1337 static struct ast_cli_entry cli_show_calls =
1338 { {"lcr", "show", "calls", NULL},
1340 "Shows current calls made by LCR and Asterisk",
1341 "Usage: lcr show calls\n",
1344 static struct ast_cli_entry cli_reload_routing =
1345 { {"lcr", "reload", "routing", NULL},
1347 "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
1348 "Usage: lcr reload routing\n",
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",
1358 static struct ast_cli_entry cli_port_block =
1359 { {"lcr", "port", "block", NULL},
1361 "Blocks LCR port for further calls",
1362 "Usage: lcr port block \"<port>\"\n",
1365 static struct ast_cli_entry cli_port_unblock =
1366 { {"lcr", "port", "unblock", NULL},
1368 "Unblocks or loads LCR port, port is opened my mISDN",
1369 "Usage: lcr port unblock \"<port>\"\n",
1372 static struct ast_cli_entry cli_port_unload =
1373 { {"lcr", "port", "unload", NULL},
1375 "Unloads LCR port, port is closes by mISDN",
1376 "Usage: lcr port unload \"<port>\"\n",
1381 * module loading and destruction
1383 int load_module(void)
1385 // ast_mutex_init(&release_lock);
1387 // lcr_cfg_update_ptp();
1389 pthread_mutex_init(&chan_lock, NULL);
1391 if (!(lcr_sock = open_socket())) {
1392 ast_log(LOG_ERROR, "Unable to connect\n");
1394 /* continue with closed socket */
1397 if (!bchannel_initialize()) {
1398 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
1399 close_socket(lcr_sock);
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);
1412 ast_cli_register(&cli_show_lcr);
1413 ast_cli_register(&cli_show_calls);
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);
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"
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"
1438 lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1440 chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
1442 //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1446 if ((pthread_create(&chan_tid, NULL, chan_thread, arg)<0))
1448 failed to create thread
1449 bchannel_deinitialize();
1450 close_socket(lcr_sock);
1451 ast_channel_unregister(&lcr_tech);
1457 int unload_module(void)
1459 /* First, take us out of the channel loop */
1460 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
1463 pthread_join(chan_tid, NULL);
1465 ast_channel_unregister(&lcr_tech);
1467 if (mISDN_created) {
1468 bchannel_deinitialize();
1472 if (lcr_sock >= 0) {
1480 static int reload_module(void)
1487 ast_mutex_t usecnt_lock;
1493 ast_mutex_lock(&usecnt_lock);
1495 ast_mutex_unlock(&usecnt_lock);
1500 char *desc="Channel driver for lcr";
1502 char *description(void)
1509 return ASTERISK_GPL_KEY;
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,