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 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
93 #include <sys/types.h>
97 #include <sys/ioctl.h>
98 #include <sys/socket.h>
102 #include <semaphore.h>
104 #include "extension.h"
106 #include "lcrsocket.h"
108 #include "bchannel.h"
109 #include "chan_lcr.h"
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>
133 CHAN_LCR_STATE // state description structure
138 char lcr_type[]="LCR";
141 pthread_mutex_t chan_lock;
147 struct admin_list *next;
148 struct admin_msg msg;
149 } *admin_first = NULL;
152 * channel and call instances
154 struct chan_call *call_first;
156 struct chan_call *find_call_ref(unsigned long ref)
158 struct chan_call *call = call_first;
162 if (call->ref == ref)
169 struct chan_call *find_call_handle(unsigned long handle)
171 struct chan_call *call = call_first;
175 if (call->bchannel_handle == handle)
182 struct chan_call *alloc_call(void)
184 struct chan_call **callp = &call_first;
187 callp = &((*callp)->next);
189 *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
191 memset(*callp, 0, sizeof(struct chan_call));
195 void free_call(struct chan_call *call)
197 struct chan_call **temp = &call_first;
203 *temp = (*temp)->next;
207 temp = &((*temp)->next);
211 unsigned short new_brige_id(void)
213 struct chan_call *call;
214 unsigned short id = 1;
216 /* search for lowest bridge id that is not in use and not 0 */
222 if (call->bridge_id == id)
235 * receive bchannel data
237 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
241 void rx_dtmf(struct bchannel *bchannel, char tone)
246 * enque message to LCR
248 int send_message(int message_type, unsigned long ref, union parameter *param)
250 struct admin_list *admin, **adminp;
252 adminp = &admin_first;
254 adminp = &((*adminp)->next);
255 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
258 admin->msg.type = message_type;
259 admin->msg.ref = ref;
260 memcpy(&admin->msg.param, param, sizeof(union parameter));
266 * incoming setup from LCR
268 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
270 struct ast_channel *ast;
271 union parameter newparam;
273 /* create asterisk channel instrance */
274 ast = ast_channel_alloc(1);
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);
286 /* set ast pointer */
289 /* fill setup information */
290 #warning todo: setup-info reinschreiben
292 /* send setup to asterisk */
293 #warning todo: setup bei der asterisk triggern
296 call->state = CHAN_LCR_STATE_IN_SETUP;
300 * incoming setup acknowledge from LCR
302 static void lcr_in_overlap(struct chan_call *call, int message_type, union parameter *param)
304 /* send pending digits in dialque */
306 send_dialing_to_lcr(call);
307 /* change to overlap state */
308 call->state = CHAN_LCR_STATE_OUT_DIALING;
312 * incoming proceeding from LCR
314 static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
317 call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
318 /* send event to asterisk */
323 * incoming alerting from LCR
325 static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
328 call->state = CHAN_LCR_STATE_OUT_ALERTING;
329 /* send event to asterisk */
334 * incoming connect from LCR
336 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
339 call->state = CHAN_LCR_STATE_CONNECT;
340 /* copy connectinfo */
342 /* send event to asterisk */
347 * incoming disconnect from LCR
349 static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param)
352 call->state = CHAN_LCR_STATE_IN_DISCONNECT;
353 /* copy disconnect info */
355 /* send event to asterisk */
360 * incoming setup acknowledge from LCR
362 static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param)
366 /* change to release state */
367 call->state = CHAN_LCR_STATE_RELEASE;
368 /* copy release info */
370 /* if we have an asterisk instance, send hangup, else we are done */
373 ast_queue_hangup(call->ast);
382 * incoming information from LCR
384 static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param)
387 todo and write them, maybe queue them for asterisk
388 /* send event to asterisk */
393 * incoming information from LCR
395 static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
397 /* copy progress info */
398 todo and write them, maybe queue them for asterisk
399 /* send event to asterisk */
401 or maybe use bride info to forward facility.
405 * message received from LCR
407 int receive_message(int message_type, unsigned long ref, union parameter *param)
409 union parameter newparam;
410 struct bchannel *bchannel;
411 struct chan_call *call;
413 memset(&newparam, 0, sizeof(union parameter));
415 /* handle bchannel message*/
416 if (message_type == MESSAGE_BCHANNEL)
418 switch(param->bchannel.type)
420 case BCHANNEL_ASSIGN:
421 if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
423 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
426 /* create bchannel */
427 bchannel = alloc_bchannel(param->bchannel.handle);
430 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
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)
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);
444 bchannel->b_txdata = 0;
445 bchannel->b_dtmf = 1;
446 bchannel->b_tx_dejitter = 1;
448 /* in case, ref is not set, this bchannel instance must
449 * be created until it is removed again by LCR */
451 if ((call = find_call_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);
458 if (bchannel_create(bchannel))
459 bchannel_activate(bchannel, 1);
462 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
463 newparam.bchannel.handle = param->bchannel.handle;
464 send_message(MESSAGE_BCHANNEL, 0, &newparam);
467 case BCHANNEL_REMOVE:
468 if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
470 #warning alle fprintf nach ast_log
471 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
474 /* unlink from call */
475 if ((call = find_call_ref(bchannel->ref)))
477 call->bchannel_handle = 0;
479 /* destroy and remove bchannel */
480 free_bchannel(bchannel);
483 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
484 newparam.bchannel.handle = param->bchannel.handle;
485 send_message(MESSAGE_BCHANNEL, 0, &newparam);
490 fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
496 if (message_type == MESSAGE_NEWREF)
498 if (param->direction)
500 /* new ref from lcr */
501 if (!ref || find_call_ref(ref))
503 fprintf(stderr, "illegal new ref %d received\n", ref);
506 /* allocate new call instance */
509 call->state = CHAN_LCR_STATE_IN_PREPARE;
512 /* wait for setup (or release from asterisk) */
515 /* new ref, as requested from this remote application */
516 call = find_call_ref(0);
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);
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)
534 newparam.disconnectinfo.cause = todo
535 newparam.disconnectinfo.location = todo
536 send_message(MESSAGE_RELEASE, ref, &newparam);
548 fprintf(stderr, "received message %d without ref\n", message_type);
551 call = find_call_ref(ref);
554 /* ignore ref that is not used (anymore) */
558 /* handle messages */
562 lcr_in_setup(call, message_type, param);
565 case MESSAGE_OVERLAP:
566 lcr_in_overlap(call, message_type, param);
569 case MESSAGE_PROCEEDING:
570 lcr_in_proceeding(call, message_type, param);
573 case MESSAGE_ALERTING:
574 lcr_in_alerting(call, message_type, param);
577 case MESSAGE_CONNECT:
578 lcr_in_connect(call, message_type, param);
581 case MESSAGE_DISCONNECT:
582 lcr_in_disconnect(call, message_type, param);
585 case MESSAGE_RELEASE:
586 lcr_in_release(call, message_type, param);
589 case MESSAGE_INFORMATION:
590 lcr_in_disconnect(call, message_type, param);
593 case MESSAGE_FACILITY:
594 lcr_in_disconnect(call, message_type, param);
597 case MESSAGE_PATTERN:
601 case MESSAGE_NOPATTERN:
605 case MESSAGE_AUDIOPATH:
617 * warning! not thread safe
618 * returns -1 for socket error, 0 for no work, 1 for work
620 int handle_socket(void)
624 struct admin_message msg;
625 struct admin_list *admin;
629 #warning SOCKET FEHLT!
630 /* read from socket */
631 len = read(sock, &msg, sizeof(msg));
634 printf("Socket closed\n");
635 return(-1); // socket closed
639 if (len != sizeof(msg))
641 fprintf(stderr, "Socket short read (%d)\n", len);
642 return(-1); // socket error
644 if (msg.message != ADMIN_MESSAGE)
646 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
647 return(-1); // socket error
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);
654 if (errno != EWOULDBLOCK)
656 fprintf(stderr, "Socket error %d\n", errno);
661 /* write to socket */
665 len = write(sock, &admin->msg, sizeof(msg));
668 printf("Socket closed\n");
669 return(-1); // socket closed
673 if (len != sizeof(msg))
675 fprintf(stderr, "Socket short write (%d)\n", len);
676 return(-1); // socket error
679 admin_first = admin->next;
685 if (errno != EWOULDBLOCK)
687 fprintf(stderr, "Socket error %d\n", errno);
696 * open and close socket
698 int open_socket(void)
702 char *socket_name = SOCKET_NAME;
704 struct sockaddr_un sock_address;
705 unsigned long on = 1;
706 union parameter param;
709 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
711 ast_log(LOG_ERROR, "Failed to create socket.\n");
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);
721 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
724 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
728 /* set non-blocking io */
729 if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
732 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
736 /* enque hello message */
737 memset(¶m, 0, sizeof(param));
738 strcpy(param.hello.application, "asterisk");
739 send_message(MESSAGE_HELLO, 0, ¶m);
744 void close_socket(int sock)
752 socket muss per timer fuer das öffnen checken
753 static void *chan_thread(void *arg)
757 pthread_mutex_lock(&chan_lock);
764 int ret = handle_socket();
771 ret = bchannel_handle();
777 pthread_mutex_unlock(&chan_lock);
779 pthread_mutex_lock(&chan_lock);
783 pthread_mutex_unlock(&chan_lock);
789 * send setup info to LCR
790 * this function is called, when asterisk call is received and ref is received
792 static void send_setup_to_lcr(struct chan_call *call)
794 if (!ast || !call->ref)
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;
806 CHRISTIAN: das war ein konflikt beim pullen
807 siehe anderes lcr_request();
808 bedenke: das ast_log muss noch üeberall eingepflegt werden
810 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
812 struct chan_call *call=alloc_call();
815 #warning hier muss jetzt wohl eine Ref angefordert werden!
816 ast=lcr_ast_new(call, ext, NULL, 0 );
821 ast_log(LOG_WARNING, "Could not create new Asterisk Channel\n");
825 ast_log(LOG_WARNING, "Could not create new Lcr Call Handle\n");
831 struct ast_channel *ast=NULL;
834 char *port_str, *ext, *p;
837 ast_copy_string(buf, data, sizeof(buf)-1);
839 port_str=strsep(&p, "/");
841 ast_verbose("portstr:%s ext:%s\n",port_str, ext);
843 sprintf(buf,"%s/%s",lcr_type,(char*)data);
847 * send dialing info to LCR
848 * this function is called, when setup acknowledge is received and dialing
851 static void send_dialing_to_lcr(struct chan_call *call)
853 if (!ast || !call->ref || !call->dialque)
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);
864 * new asterisk instance
866 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
868 pthread_mutex_lock(&chan_lock);
870 /* create call instance */
874 /* failed to create instance */
877 /* create asterisk channel instrance */
878 ast = ast_channel_alloc(1);
882 /* failed to create instance */
886 ast->tech_pvt = call;
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);
893 call->state = CHAN_LCR_STATE_OUT_PREPARE;
895 pthread_mutex_unlock(&chan_lock);
901 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
903 struct chan_call *call=ast->tech_pvt;
905 char *port_str, *dad, *p;
907 if (!call) return -1;
909 pthread_mutex_lock(&chan_lock);
912 ast_copy_string(buf, dest, sizeof(buf)-1);
914 port_str=strsep(&p, "/");
917 /* send setup message, if we already have a callref */
919 send_setup_to_lcr(call);
922 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
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.
926 pthread_mutex_unlock(&chan_lock);
930 static int lcr_digit(struct ast_channel *ast, char digit)
934 if (!call) return -1;
936 /* only pass IA5 number space */
937 if (digit > 126 || digit < 32)
940 pthread_mutex_lock(&chan_lock);
942 /* send information or queue them */
943 if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
945 send_dialing_to_lcr(call);
948 && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
951 strncat(call->dialque, buf, strlen(char->dialque)-1);
954 digits kommen, koennen aber nicht verwendet werden.
955 sollen wir sie als info senden (im connect zb.)
958 pthread_mutex_unlock(&chan_lock);
963 static int lcr_answer(struct ast_channel *c)
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);
972 static int lcr_hangup(struct ast_channel *ast)
974 struct chan_call *call = ast->tech_pvt;
979 pthread_mutex_lock(&chan_lock);
980 /* disconnect asterisk, maybe not required */
981 ast->tech_pvt = NULL;
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);
991 pthread_mutex_unlock(&chan_lock);
995 /* ref is not set, due to prepare setup or release */
996 if (call->state == CHAN_LCR_STATE_RELEASE)
998 /* we get the response to our release */
1002 /* during prepare, we change to release state */
1003 call->state = CHAN_LCR_STATE_RELEASE;
1006 pthread_mutex_unlock(&chan_lock);
1010 static int lcr_write(struct ast_channel *c, struct ast_frame *f)
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);
1019 static struct ast_frame *lcr_read(struct ast_channel *c)
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);
1027 static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
1030 if (!call) return -1;
1032 pthread_mutex_lock(&chan_lock);
1035 case AST_CONTROL_BUSY:
1036 case AST_CONTROL_CONGESTION:
1037 case AST_CONTROL_RINGING:
1038 pthread_mutex_unlock(&chan_lock);
1041 pthread_mutex_unlock(&chan_lock);
1044 case AST_CONTROL_VIDUPDATE:
1047 case AST_CONTROL_HOLD:
1048 ast_verbose(" << Console Has Been Placed on Hold >> \n");
1049 //ast_moh_start(c, data, g->mohinterpret);
1051 case AST_CONTROL_UNHOLD:
1052 ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
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);
1062 pthread_mutex_unlock(&chan_lock);
1066 static struct ast_channel_tech lcr_tech = {
1068 .description="Channel driver for connecting to Linux-Call-Router",
1069 .capabilities=AST_FORMAT_ALAW,
1070 .requester=lcr_request,
1071 .send_digit=lcr_digit,
1073 // .bridge=lcr_bridge,
1078 .indicate=lcr_indicate,
1079 // .fixup=lcr_fixup,
1080 // .send_text=lcr_send_text,
1084 #warning das muss mal aus der config datei gelesen werden:
1085 char lcr_context[]="from-lcr";
1087 static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref)
1089 struct ast_channel *tmp;
1090 char *cid_name = 0, *cid_num = 0;
1094 ast_callerid_parse(callerid, &cid_name, &cid_num);
1096 tmp = ast_channel_alloc(1, AST_STATE_RESERVED, cid_num, cid_name, "", exten, "", 0, "%s/%d", lcr_type, ref);
1099 tmp->tech = &lcr_tech;
1100 tmp->writeformat = AST_FORMAT_ALAW;
1101 tmp->readformat = AST_FORMAT_ALAW;
1103 ast_copy_string(tmp->context, lcr_context, AST_MAX_CONTEXT);
1115 static int lcr_show_lcr (int fd, int argc, char *argv[])
1119 static int lcr_show_calls (int fd, int argc, char *argv[])
1123 static int lcr_reload_routing (int fd, int argc, char *argv[])
1127 static int lcr_reload_interfaces (int fd, int argc, char *argv[])
1131 static int lcr_port_block (int fd, int argc, char *argv[])
1135 static int lcr_port_unblock (int fd, int argc, char *argv[])
1139 static int lcr_port_unload (int fd, int argc, char *argv[])
1143 static struct ast_cli_entry cli_show_lcr =
1144 { {"lcr", "show", "lcr", NULL},
1146 "Shows current states of LCR core",
1147 "Usage: lcr show lcr\n",
1150 static struct ast_cli_entry cli_show_calls =
1151 { {"lcr", "show", "calls", NULL},
1153 "Shows current calls made by LCR and Asterisk",
1154 "Usage: lcr show calls\n",
1157 static struct ast_cli_entry cli_reload_routing =
1158 { {"lcr", "reload", "routing", NULL},
1160 "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
1161 "Usage: lcr reload routing\n",
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",
1171 static struct ast_cli_entry cli_port_block =
1172 { {"lcr", "port", "block", NULL},
1174 "Blocks LCR port for further calls",
1175 "Usage: lcr port block \"<port>\"\n",
1178 static struct ast_cli_entry cli_port_unblock =
1179 { {"lcr", "port", "unblock", NULL},
1181 "Unblocks or loads LCR port, port is opened my mISDN",
1182 "Usage: lcr port unblock \"<port>\"\n",
1185 static struct ast_cli_entry cli_port_unload =
1186 { {"lcr", "port", "unload", NULL},
1188 "Unloads LCR port, port is closes by mISDN",
1189 "Usage: lcr port unload \"<port>\"\n",
1194 * module loading and destruction
1196 int load_module(void)
1198 // ast_mutex_init(&release_lock);
1200 // lcr_cfg_update_ptp();
1202 pthread_mutex_init(&chan_lock, NULL);
1204 if (!(lcr_sock = open_socket())) {
1205 ast_log(LOG_ERROR, "Unable to connect\n");
1207 /* continue with closed socket */
1210 if (!bchannel_initialize()) {
1211 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
1216 if (ast_channel_register(&lcr_tech)) {
1217 ast_log(LOG_ERROR, "Unable to register channel class\n");
1222 ast_cli_register(&cli_show_lcr);
1223 ast_cli_register(&cli_show_calls);
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);
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"
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"
1248 lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1250 chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
1252 //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1256 if ((pthread_create(&chan_tid, NULL, chan_thread, arg)<0))
1258 failed to create thread
1264 int unload_module(void)
1266 /* First, take us out of the channel loop */
1267 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
1270 pthread_join(chan_tid, NULL);
1272 ast_channel_unregister(&lcr_tech);
1274 if (mISDN_created) {
1275 bchannel_deinitialize();
1279 if (lcr_sock >= 0) {
1287 static int reload_module(void)
1294 ast_mutex_t usecnt_lock;
1300 ast_mutex_lock(&usecnt_lock);
1302 ast_mutex_unlock(&usecnt_lock);
1307 char *desc="Channel driver for lcr";
1309 char *description(void)
1316 return ASTERISK_GPL_KEY;
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,