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 todo (before first compile)
83 reconnect after socket closed, release all calls.
84 debug of call handling
85 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 call->bch->call = NULL;
212 temp = &((*temp)->next);
216 unsigned short new_brige_id(void)
218 struct chan_call *call;
219 unsigned short id = 1;
221 /* search for lowest bridge id that is not in use and not 0 */
227 if (call->bridge_id == id)
240 * receive bchannel data
242 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
246 void rx_dtmf(struct bchannel *bchannel, char tone)
251 * enque message to LCR
253 int send_message(int message_type, unsigned long ref, union parameter *param)
255 struct admin_list *admin, **adminp;
257 adminp = &admin_first;
259 adminp = &((*adminp)->next);
260 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
263 admin->msg.type = message_type;
264 admin->msg.ref = ref;
265 memcpy(&admin->msg.param, param, sizeof(union parameter));
271 * in case of a bridge, the unsupported message can be forwarded directly
272 * to the remote call.
274 static void bridge_message_if_bridged(struct chan_call *call, int message_type, union parameter *param)
278 if (!call->channel) return;
279 if (!call->channel->bridge_channel) return;
280 if (!call->channel->bridge_channel->call) return;
281 if (!call->channel->bridge_channel->call->ref) return;
282 send_message(MESSAGE_RELEASE, call->channel->bridge_channel->call->ref, param);
286 * incoming setup from LCR
288 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
290 struct ast_channel *ast;
291 union parameter newparam;
293 /* create asterisk channel instrance */
294 ast = ast_channel_alloc(1);
298 memset(&newparam, 0, sizeof(union parameter));
299 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
300 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
301 send_message(MESSAGE_RELEASE, call->ref, &newparam);
306 /* set ast pointer */
308 ast->tech_pvt = call;
309 ast->tech = &lcr_tech;
311 /* fill setup information */
312 if (param->setup.exten[0])
313 strdup(ast->exten, param->setup.exten);
314 if (param->setup.callerinfo.id[0])
315 strdup(ast->cid->cid_num, param->setup.callerinfo.id);
316 if (param->setup.callerinfo.name[0])
317 strdup(ast->cid->cid_name, param->setup.callerinfo.name);
318 if (param->setup.redirinfo.id[0])
319 strdup(ast->cid->cid_name, numberrize_callerinfo(param->setup.callerinfo.name, param->setup.callerinfo.ntype, configfile->prefix_nat, configfile->prefix_inter));
320 switch (param->setup.callerinfo.present)
322 case INFO_PRESENT_ALLOWED:
323 ast->cid->cid_pres = AST_PRESENT_ALLOWED;
325 case INFO_PRESENT_RESTRICTED:
326 ast->cid->cid_pres = AST_PRESENT_RESTRICTED;
329 ast->cid->cid_pres = AST_PRESENT_UNAVAILABLE;
331 switch (param->setup.callerinfo.ntype)
333 case INFO_NTYPE_SUBSCRIBER:
334 ast->cid->cid_ton = AST_wasnu;
336 case INFO_NTYPE_NATIONAL:
337 ast->cid->cid_ton = AST_wasnu;
339 case INFO_NTYPE_INTERNATIONAL:
340 ast->cid->cid_ton = AST_wasnu;
343 ast->cid->cid_ton = AST_wasnu;
345 ast->transfercapability = param->setup.bearerinfo.capability;
347 /* configure channel */
348 ast->state = AST_STATE_RESERVED;
349 snprintf(ast->name, sizeof(ast->name), "%s/%d", lcr_type, ++glob_channel);
350 ast->name[sizeof(ast->name)-1] = '\0';
351 ast->type = lcr_type;
352 ast->nativeformat = configfile->lawformat;
353 ast->readformat = ast->rawreadformat = configfile->lawformat;
354 ast->writeformat = ast->rawwriteformat = configfile->lawformat;
355 ast->hangupcause = 0;
358 call->state = CHAN_LCR_STATE_IN_SETUP;
360 /* send setup to asterisk */
363 /* send setup acknowledge to lcr */
364 memset(&newparam, 0, sizeof(union parameter));
365 send_message(MESSAGE_OVERLAP, call->ref, &newparam);
368 call->state = CHAN_LCR_STATE_IN_DIALING;
372 * incoming setup acknowledge from LCR
374 static void lcr_in_overlap(struct chan_call *call, int message_type, union parameter *param)
376 if (!call->ast) return;
378 /* send pending digits in dialque */
380 send_dialque_to_lcr(call);
381 /* change to overlap state */
382 call->state = CHAN_LCR_STATE_OUT_DIALING;
386 * incoming proceeding from LCR
388 static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
391 call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
392 /* send event to asterisk */
394 ast_queue_control(ast, AST_CONTROL_PROCEEDING);
398 * incoming alerting from LCR
400 static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
403 call->state = CHAN_LCR_STATE_OUT_ALERTING;
404 /* send event to asterisk */
406 ast_queue_control(ast, AST_CONTROL_RINGING);
410 * incoming connect from LCR
412 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
415 call->state = CHAN_LCR_STATE_CONNECT;
416 /* copy connectinfo */
417 memcpy(call->connectinfo, param->connectinfo, sizeof(struct connect_info));
418 /* send event to asterisk */
420 ast_queue_control(ast, AST_CONTROL_ANSWER);
424 * incoming disconnect from LCR
426 static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param)
428 union parameter newparam;
431 call->state = CHAN_LCR_STATE_IN_DISCONNECT;
433 call->cause = param.disconnectinfo.cause;
434 call->location = param.disconnectinfo.location;
435 /* if bridge, forward disconnect and return */
437 if (call->channel->bridge_channel)
438 if (call->channel->bridge_channel->call)
440 bridge_message_if_bridged(call, message_type, param);
444 newparam.disconnectinfo.cause = CAUSE_NORMAL;
445 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
446 send_message(MESSAGE_RELEASE, ref, &newparam);
448 /* release asterisk */
449 call->ast->hangupcause = call->cause;
450 ast_queue_hangup(call->ast);
451 /* change to release state */
452 call->state = CHAN_LCR_STATE_RELEASE;
456 * incoming setup acknowledge from LCR
458 static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param)
462 /* change to release state */
463 call->state = CHAN_LCR_STATE_RELEASE;
464 /* copy release info */
466 call->cause = param.disconnectinfo.cause;
467 /* if we have an asterisk instance, send hangup, else we are done */
470 call->ast->hangupcause = call->cause;
471 ast_queue_hangup(call->ast);
480 * incoming information from LCR
482 static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param)
487 if (!call->ast) return;
490 p = param->dialinginfo.id;
491 if (call->state == CHAN_LCR_STATE_IN_DIALING && *p)
495 /* send digit to asterisk */
496 memset(&fr, 0, sizeof(fr));
497 fr.frametype = AST_FRAME_DTMF;
499 fr.delivery = ast_tv(0, 0);
500 ast_queue_frame(call->ast, &fr);
504 /* use bridge to forware message not supported by asterisk */
505 if (call->state == CHAN_LCR_STATE_CONNECT)
506 bridge_message_if_bridged(call, message_type, param);
510 * incoming information from LCR
512 static void lcr_in_notify(struct chan_call *call, int message_type, union parameter *param)
514 if (!call->ast) return;
516 /* use bridge to forware message not supported by asterisk */
517 bridge_message_if_bridged(call, message_type, param);
521 * incoming information from LCR
523 static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
525 if (!call->ast) return;
527 /* use bridge to forware message not supported by asterisk */
528 bridge_message_if_bridged(call, message_type, param);
532 * message received from LCR
534 int receive_message(int message_type, unsigned long ref, union parameter *param)
536 union parameter newparam;
537 struct bchannel *bchannel;
538 struct chan_call *call;
540 memset(&newparam, 0, sizeof(union parameter));
542 /* handle bchannel message*/
543 if (message_type == MESSAGE_BCHANNEL)
545 switch(param->bchannel.type)
547 case BCHANNEL_ASSIGN:
548 if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
550 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
553 /* create bchannel */
554 bchannel = alloc_bchannel(param->bchannel.handle);
557 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
561 /* configure channel */
562 bchannel->b_tx_gain = param->bchannel.tx_gain;
563 bchannel->b_rx_gain = param->bchannel.rx_gain;
564 strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
565 if (param->bchannel.crypt_len)
567 bchannel->b_crypt_len = param->bchannel.crypt_len;
568 bchannel->b_crypt_type = param->bchannel.crypt_type;
569 memcpy(bchannel->b_crypt_key, param->bchannel.crypt, param->bchannel.crypt_len);
571 bchannel->b_txdata = 0;
572 bchannel->b_dtmf = 1;
573 bchannel->b_tx_dejitter = 1;
575 /* in case, ref is not set, this bchannel instance must
576 * be created until it is removed again by LCR */
578 if ((call = find_call_ref(ref)))
581 call->bchannel_handle = param->bchannel.handle;
582 #warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
583 bchannel_join(bchannel, call->bridge_id);
585 if (bchannel_create(bchannel))
586 bchannel_activate(bchannel, 1);
589 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
590 newparam.bchannel.handle = param->bchannel.handle;
591 send_message(MESSAGE_BCHANNEL, 0, &newparam);
594 case BCHANNEL_REMOVE:
595 if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
597 #warning alle fprintf nach ast_log
598 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
601 /* unlink from call */
602 if ((call = find_call_ref(bchannel->ref)))
604 call->bchannel_handle = 0;
606 /* destroy and remove bchannel */
607 free_bchannel(bchannel);
610 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
611 newparam.bchannel.handle = param->bchannel.handle;
612 send_message(MESSAGE_BCHANNEL, 0, &newparam);
617 fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
623 if (message_type == MESSAGE_NEWREF)
625 if (param->direction)
627 /* new ref from lcr */
628 if (!ref || find_call_ref(ref))
630 fprintf(stderr, "illegal new ref %d received\n", ref);
633 /* allocate new call instance */
636 call->state = CHAN_LCR_STATE_IN_PREPARE;
639 /* wait for setup (or release from asterisk) */
642 /* new ref, as requested from this remote application */
643 call = find_call_ref(0);
646 /* send release, if ref does not exist */
647 newparam.disconnectinfo.cause = CAUSE_NORMAL;
648 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
649 send_message(MESSAGE_RELEASE, ref, &newparam);
654 /* send pending setup info */
655 if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
656 send_setup_to_lcr(call);
657 /* release if asterisk has signed off */
658 else if (call->state == CHAN_LCR_STATE_RELEASE)
661 newparam.disconnectinfo.cause = todo
662 newparam.disconnectinfo.location = todo
663 send_message(MESSAGE_RELEASE, ref, &newparam);
675 fprintf(stderr, "received message %d without ref\n", message_type);
678 call = find_call_ref(ref);
681 /* ignore ref that is not used (anymore) */
685 /* handle messages */
689 lcr_in_setup(call, message_type, param);
692 case MESSAGE_OVERLAP:
693 lcr_in_overlap(call, message_type, param);
696 case MESSAGE_PROCEEDING:
697 lcr_in_proceeding(call, message_type, param);
700 case MESSAGE_ALERTING:
701 lcr_in_alerting(call, message_type, param);
704 case MESSAGE_CONNECT:
705 lcr_in_connect(call, message_type, param);
708 case MESSAGE_DISCONNECT:
709 lcr_in_disconnect(call, message_type, param);
712 case MESSAGE_RELEASE:
713 lcr_in_release(call, message_type, param);
716 case MESSAGE_INFORMATION:
717 lcr_in_disconnect(call, message_type, param);
721 lcr_in_notify(call, message_type, param);
724 case MESSAGE_FACILITY:
725 lcr_in_facility(call, message_type, param);
728 case MESSAGE_PATTERN:
732 case MESSAGE_NOPATTERN:
736 case MESSAGE_AUDIOPATH:
748 * warning! not thread safe
749 * returns -1 for socket error, 0 for no work, 1 for work
751 int handle_socket(void)
755 struct admin_message msg;
756 struct admin_list *admin;
760 #warning SOCKET FEHLT!
761 /* read from socket */
762 len = read(sock, &msg, sizeof(msg));
765 printf("Socket closed\n");
766 return(-1); // socket closed
770 if (len != sizeof(msg))
772 fprintf(stderr, "Socket short read (%d)\n", len);
773 return(-1); // socket error
775 if (msg.message != ADMIN_MESSAGE)
777 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
778 return(-1); // socket error
780 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
781 printf("message received %d\n", msg.u.msg.type);
785 if (errno != EWOULDBLOCK)
787 fprintf(stderr, "Socket error %d\n", errno);
792 /* write to socket */
796 len = write(sock, &admin->msg, sizeof(msg));
799 printf("Socket closed\n");
800 return(-1); // socket closed
804 if (len != sizeof(msg))
806 fprintf(stderr, "Socket short write (%d)\n", len);
807 return(-1); // socket error
810 admin_first = admin->next;
816 if (errno != EWOULDBLOCK)
818 fprintf(stderr, "Socket error %d\n", errno);
827 * open and close socket
829 int open_socket(void)
833 char *socket_name = SOCKET_NAME;
835 struct sockaddr_un sock_address;
836 unsigned long on = 1;
837 union parameter param;
840 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
842 ast_log(LOG_ERROR, "Failed to create socket.\n");
846 /* set socket address and name */
847 memset(&sock_address, 0, sizeof(sock_address));
848 sock_address.sun_family = PF_UNIX;
849 strcpy(sock_address.sun_path, socket_name);
852 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
855 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
859 /* set non-blocking io */
860 if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
863 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
867 /* enque hello message */
868 memset(¶m, 0, sizeof(param));
869 strcpy(param.hello.application, "asterisk");
870 send_message(MESSAGE_HELLO, 0, ¶m);
875 void close_socket(int sock)
883 socket muss per timer fuer das öffnen checken
884 static void *chan_thread(void *arg)
888 pthread_mutex_lock(&chan_lock);
895 int ret = handle_socket();
902 ret = bchannel_handle();
908 pthread_mutex_unlock(&chan_lock);
910 pthread_mutex_lock(&chan_lock);
914 pthread_mutex_unlock(&chan_lock);
920 * send setup info to LCR
921 * this function is called, when asterisk call is received and ref is received
923 static void send_setup_to_lcr(struct chan_call *call)
925 union parameter newparam;
927 if (!ast || !call->ref)
930 /* send setup message to LCR */
931 memset(&newparam, 0, sizeof(union parameter));
932 newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;
933 newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
934 if (ast->cid->cid_num) if (ast->cid->cid_num[0])
935 strncpy(newparam.setup.callerinfo.id, ast->cid->cid_num, sizeof(newparam.setup.callerinfo.id)-1);
936 if (ast->cid->cid_name) if (ast->cid->cid_name[0])
937 strncpy(newparam.setup.callerinfo.name, ast->cid->cid_name, sizeof(newparam.setup.callerinfo.name)-1);
938 if (ast->cid->cid_rdnis) if (ast->cid->cid_rdnis[0])
940 strncpy(newparam.setup.redirinfo.id, ast->cid->cid_rdnis, sizeof(newparam.setup.redirinfo.id)-1);
941 newparam.setup.redirinfo.itype = INFO_ITYPE_CHAN;
942 newparam.setup.redirinfo.ntype = INFO_NTYPE_UNKNOWN;
944 switch(ast->cid->cid_pres & AST_PRES_RESTRICTION)
946 case AST_PRES_ALLOWED:
947 newparam.setup.callerinfo.present = INFO_PRESENT_ALLOWED;
949 case AST_PRES_RESTRICTED:
950 newparam.setup.callerinfo.present = INFO_PRESENT_RESTRICTED;
952 case AST_PRES_UNAVAILABLE:
953 newparam.setup.callerinfo.present = INFO_PRESENT_NOTAVAIL;
956 newparam.setup.callerinfo.present = INFO_PRESENT_NULL;
958 switch(ast->cid->cid_ton)
961 newparam.setup.callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
964 newparam.setup.callerinfo.ntype = INFO_NTYPE_NATIONAL;
967 newparam.setup.callerinfo.ntype = INFO_NTYPE_INTERNATIONAL;
970 newparam.setup.capainfo.bearer_capa = ast->transfercapability;
971 newparam.setup.capainfo.bearer_user = alaw 3, ulaw 2;
972 newparam.setup.capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
973 newparam.setup.capainfo.hlc = INFO_HLC_NONE;
974 newparam.setup.capainfo.exthlc = INFO_HLC_NONE;
975 send_message(MESSAGE_SETUP, call->ref, &newparam);
977 /* change to outgoing setup state */
978 call->state = CHAN_LCR_STATE_OUT_SETUP;
982 CHRISTIAN: das war ein konflikt beim pullen
983 siehe anderes lcr_request();
984 bedenke: das ast_log muss noch üeberall eingepflegt werden
986 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
988 struct chan_call *call=alloc_call();
991 #warning hier muss jetzt wohl eine Ref angefordert werden!
992 ast=lcr_ast_new(call, ext, NULL, 0 );
997 ast_log(LOG_WARNING, "Could not create new Asterisk Channel\n");
1001 ast_log(LOG_WARNING, "Could not create new Lcr Call Handle\n");
1007 struct ast_channel *ast=NULL;
1010 char *port_str, *ext, *p;
1013 ast_copy_string(buf, data, sizeof(buf)-1);
1015 port_str=strsep(&p, "/");
1016 ext=strsep(&p, "/");
1017 ast_verbose("portstr:%s ext:%s\n",port_str, ext);
1019 sprintf(buf,"%s/%s",lcr_type,(char*)data);
1023 * send dialing info to LCR
1024 * this function is called, when setup acknowledge is received and dialing
1025 * info is available.
1027 static void send_dialque_to_lcr(struct chan_call *call)
1029 union parameter newparam;
1031 if (!ast || !call->ref || !call->dialque)
1034 /* send setup message to LCR */
1035 memset(&newparam, 0, sizeof(union parameter));
1036 strncpy(newparam.dialinginfo.id, call->dialque, sizeof(newparam.dialinginfo.id)-1);
1037 call->dialque[0] = '\0';
1038 send_message(MESSAGE_INFORMATION, call->ref, &newparam);
1042 * new asterisk instance
1044 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
1046 union parameter newparam;
1048 pthread_mutex_lock(&chan_lock);
1050 /* create call instance */
1051 call = alloc_call();
1054 /* failed to create instance */
1057 /* create asterisk channel instrance */
1058 ast = ast_channel_alloc(1);
1062 /* failed to create instance */
1066 ast->tech_pvt = call;
1068 ast->tech = &lcr_tech;
1069 /* configure channel */
1070 ast->state = AST_STATE_RESERVED;
1071 snprintf(ast->name, sizeof(ast->name), "%s/%d", lcr_type, ++glob_channel);
1072 ast->name[sizeof(ast->name)-1] = '\0';
1073 ast->type = lcr_type;
1074 ast->nativeformat = configfile->lawformat;
1075 ast->readformat = ast->rawreadformat = configfile->lawformat;
1076 ast->writeformat = ast->rawwriteformat = configfile->lawformat;
1077 ast->hangupcause = 0;
1078 /* send MESSAGE_NEWREF */
1079 memset(&newparam, 0, sizeof(union parameter));
1080 newparam.direction = 0; /* request from app */
1081 send_message(MESSAGE_NEWREF, 0, &newparam);
1083 call->state = CHAN_LCR_STATE_OUT_PREPARE;
1085 pthread_mutex_unlock(&chan_lock);
1089 * call from asterisk
1091 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
1093 union parameter newparam;
1094 struct chan_call *call=ast->tech_pvt;
1096 char *port_str, *dad, *p;
1098 if (!call) return -1;
1100 pthread_mutex_lock(&chan_lock);
1103 ast_copy_string(buf, dest, sizeof(buf)-1);
1105 port_str=strsep(&p, "/");
1106 dad=strsep(&p, "/");
1108 /* send setup message, if we already have a callref */
1110 send_setup_to_lcr(call);
1113 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
1115 #warning hier müssen wi eine der geholten REFs nehmen und ein SETUP schicken, die INFOS zum SETUP stehen im Ast pointer drin, bzw. werden hier übergeben.
1117 pthread_mutex_unlock(&chan_lock);
1121 static int lcr_digit(struct ast_channel *ast, char digit)
1123 union parameter newparam;
1126 if (!call) return -1;
1128 /* only pass IA5 number space */
1129 if (digit > 126 || digit < 32)
1132 pthread_mutex_lock(&chan_lock);
1134 /* send information or queue them */
1135 if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
1137 memset(&newparam, 0, sizeof(union parameter));
1138 newparam.dialinginfo.id[0] = digit;
1139 newparam.dialinginfo.id[1] = '\0';
1140 send_message(MESSAGE_INFORMATION, call->ref, &newparam);
1143 && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
1146 strncat(call->dialque, buf, strlen(char->dialque)-1);
1149 pthread_mutex_unlock(&chan_lock);
1154 static int lcr_answer(struct ast_channel *c)
1156 union parameter newparam;
1157 struct chan_call *call=c->tech_pvt;
1159 if (!call) return -1;
1161 pthread_mutex_lock(&chan_lock);
1163 /* check bridged connectinfo */
1165 if (call->bchannel->bridge_channel)
1166 if (call->bchannel->bridge_channel->call)
1168 memcpy(call->connectinfo, call->bchannel->bridge_channel->call->connectinfo, sizeof(struct connect_info));
1170 /* send connect message to lcr */
1171 memset(&newparam, 0, sizeof(union parameter));
1172 memcpy(param->connectinfo, call->connectinfo, sizeof(struct connect_info));
1173 send_message(MESSAGE_CONNECT, call->ref, &newparam);
1175 call->state = CHAN_LCR_STATE_CONNECT;
1177 pthread_mutex_unlock(&chan_lock);
1181 static int lcr_hangup(struct ast_channel *ast)
1183 union parameter newparam;
1184 struct chan_call *call = ast->tech_pvt;
1189 pthread_mutex_lock(&chan_lock);
1190 /* disconnect asterisk, maybe not required */
1191 ast->tech_pvt = NULL;
1195 memset(&newparam, 0, sizeof(union parameter));
1196 newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
1197 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1198 send_message(MESSAGE_RELEASE, call->ref, &newparam);
1201 pthread_mutex_unlock(&chan_lock);
1205 /* ref is not set, due to prepare setup or release */
1206 if (call->state == CHAN_LCR_STATE_RELEASE)
1208 /* we get the response to our release */
1212 /* during prepare, we change to release state */
1213 call->state = CHAN_LCR_STATE_RELEASE;
1216 pthread_mutex_unlock(&chan_lock);
1220 static int lcr_write(struct ast_channel *ast, struct ast_frame *f)
1222 struct chan_call *call= ast->tech_pvt;
1223 if (!call) return 0;
1224 pthread_mutex_lock(&chan_lock);
1225 pthread_mutex_unlock(&chan_lock);
1229 static struct ast_frame *lcr_read(struct ast_channel *ast)
1231 struct chan_call *call = ast->tech_pvt;
1232 if (!call) return 0;
1233 pthread_mutex_lock(&chan_lock);
1234 pthread_mutex_unlock(&chan_lock);
1237 static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, size_t datalen)
1239 union parameter newparam;
1242 if (!call) return -1;
1244 pthread_mutex_lock(&chan_lock);
1247 case AST_CONTROL_BUSY:
1248 /* send message to lcr */
1249 memset(&newparam, 0, sizeof(union parameter));
1250 newparam.disconnectinfo.cause = 17;
1251 newparam.disconnectinfo.location = 5;
1252 send_message(MESSAGE_DISCONNECT, call->ref, &newparam);
1254 call->state = CHAN_LCR_STATE_OUT_DISCONNECT;
1256 pthread_mutex_unlock(&chan_lock);
1258 case AST_CONTROL_CONGESTION:
1260 pthread_mutex_unlock(&chan_lock);
1262 case AST_CONTROL_RINGING:
1263 /* send message to lcr */
1264 memset(&newparam, 0, sizeof(union parameter));
1265 send_message(MESSAGE_ALERTING, call->ref, &newparam);
1267 call->state = CHAN_LCR_STATE_OUT_ALERTING;
1269 pthread_mutex_unlock(&chan_lock);
1273 pthread_mutex_unlock(&chan_lock);
1276 case AST_CONTROL_VIDUPDATE:
1279 case AST_CONTROL_HOLD:
1280 /* send message to lcr */
1281 memset(&newparam, 0, sizeof(union parameter));
1282 newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
1283 send_message(MESSAGE_NOTIFY, call->ref, &newparam);
1285 case AST_CONTROL_UNHOLD:
1286 /* send message to lcr */
1287 memset(&newparam, 0, sizeof(union parameter));
1288 newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
1289 send_message(MESSAGE_NOTIFY, call->ref, &newparam);
1293 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
1295 pthread_mutex_unlock(&chan_lock);
1300 pthread_mutex_unlock(&chan_lock);
1304 static struct ast_channel_tech lcr_tech = {
1306 .description="Channel driver for connecting to Linux-Call-Router",
1307 .capabilities=AST_FORMAT_ALAW,
1308 .requester=lcr_request,
1309 .send_digit=lcr_digit,
1316 .indicate=lcr_indicate,
1317 // .fixup=lcr_fixup,
1318 // .send_text=lcr_send_text,
1322 #warning das muss mal aus der config datei gelesen werden:
1323 char lcr_context[]="from-lcr";
1326 TODO: muss oben ins lcr_in setup und ins lcr_request
1327 static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref)
1329 struct ast_channel *tmp;
1330 char *cid_name = 0, *cid_num = 0;
1334 ast_callerid_parse(callerid, &cid_name, &cid_num);
1336 tmp = ast_channel_alloc(1, AST_STATE_RESERVED, cid_num, cid_name, "", exten, "", 0, "%s/%d", lcr_type, ref);
1339 tmp->tech = &lcr_tech;
1340 tmp->writeformat = AST_FORMAT_ALAW;
1341 tmp->readformat = AST_FORMAT_ALAW;
1343 ast_copy_string(tmp->context, lcr_context, AST_MAX_CONTEXT);
1355 static int lcr_show_lcr (int fd, int argc, char *argv[])
1359 static int lcr_show_calls (int fd, int argc, char *argv[])
1363 static int lcr_reload_routing (int fd, int argc, char *argv[])
1367 static int lcr_reload_interfaces (int fd, int argc, char *argv[])
1371 static int lcr_port_block (int fd, int argc, char *argv[])
1375 static int lcr_port_unblock (int fd, int argc, char *argv[])
1379 static int lcr_port_unload (int fd, int argc, char *argv[])
1383 static struct ast_cli_entry cli_show_lcr =
1384 { {"lcr", "show", "lcr", NULL},
1386 "Shows current states of LCR core",
1387 "Usage: lcr show lcr\n",
1390 static struct ast_cli_entry cli_show_calls =
1391 { {"lcr", "show", "calls", NULL},
1393 "Shows current calls made by LCR and Asterisk",
1394 "Usage: lcr show calls\n",
1397 static struct ast_cli_entry cli_reload_routing =
1398 { {"lcr", "reload", "routing", NULL},
1400 "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
1401 "Usage: lcr reload routing\n",
1404 static struct ast_cli_entry cli_reload_interfaces =
1405 { {"lcr", "reload", "interfaces", NULL},
1406 lcr_reload_interfaces,
1407 "Reloads interfaces conf of LCR",
1408 "Usage: lcr reload interfaces\n",
1411 static struct ast_cli_entry cli_port_block =
1412 { {"lcr", "port", "block", NULL},
1414 "Blocks LCR port for further calls",
1415 "Usage: lcr port block \"<port>\"\n",
1418 static struct ast_cli_entry cli_port_unblock =
1419 { {"lcr", "port", "unblock", NULL},
1421 "Unblocks or loads LCR port, port is opened my mISDN",
1422 "Usage: lcr port unblock \"<port>\"\n",
1425 static struct ast_cli_entry cli_port_unload =
1426 { {"lcr", "port", "unload", NULL},
1428 "Unloads LCR port, port is closes by mISDN",
1429 "Usage: lcr port unload \"<port>\"\n",
1434 * module loading and destruction
1436 int load_module(void)
1438 // ast_mutex_init(&release_lock);
1440 // lcr_cfg_update_ptp();
1442 pthread_mutex_init(&chan_lock, NULL);
1444 if (!(lcr_sock = open_socket())) {
1445 ast_log(LOG_ERROR, "Unable to connect\n");
1447 /* continue with closed socket */
1450 if (!bchannel_initialize()) {
1451 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
1452 close_socket(lcr_sock);
1457 if (ast_channel_register(&lcr_tech)) {
1458 ast_log(LOG_ERROR, "Unable to register channel class\n");
1459 bchannel_deinitialize();
1460 close_socket(lcr_sock);
1465 ast_cli_register(&cli_show_lcr);
1466 ast_cli_register(&cli_show_calls);
1468 ast_cli_register(&cli_reload_routing);
1469 ast_cli_register(&cli_reload_interfaces);
1470 ast_cli_register(&cli_port_block);
1471 ast_cli_register(&cli_port_unblock);
1472 ast_cli_register(&cli_port_unload);
1474 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
1475 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
1476 "Sets mISDN opts. and optargs\n"
1478 "The available options are:\n"
1479 " d - Send display text on called phone, text is the optparam\n"
1480 " n - don't detect dtmf tones on called channel\n"
1481 " h - make digital outgoing call\n"
1482 " c - make crypted outgoing call, param is keyindex\n"
1483 " e - perform echo cancelation on this channel,\n"
1484 " takes taps as arguments (32,64,128,256)\n"
1485 " s - send Non Inband DTMF as inband\n"
1486 " vr - rxgain control\n"
1487 " vt - txgain control\n"
1491 lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1493 chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
1495 //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1499 if ((pthread_create(&chan_tid, NULL, chan_thread, arg)<0))
1501 failed to create thread
1502 bchannel_deinitialize();
1503 close_socket(lcr_sock);
1504 ast_channel_unregister(&lcr_tech);
1510 int unload_module(void)
1512 /* First, take us out of the channel loop */
1513 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
1516 pthread_join(chan_tid, NULL);
1518 ast_channel_unregister(&lcr_tech);
1520 if (mISDN_created) {
1521 bchannel_deinitialize();
1525 if (lcr_sock >= 0) {
1533 static int reload_module(void)
1540 ast_mutex_t usecnt_lock;
1546 ast_mutex_lock(&usecnt_lock);
1548 ast_mutex_unlock(&usecnt_lock);
1553 char *desc="Channel driver for lcr";
1555 char *description(void)
1562 return ASTERISK_GPL_KEY;
1565 #define AST_MODULE "chan_lcr"
1566 AST_MODULE_INFO(ASTERISK_GPL_KEY,
1567 AST_MODFLAG_DEFAULT,
1568 "Channel driver for LCR",
1569 .load = load_module,
1570 .unload = unload_module,
1571 .reload = reload_module,