1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** Asterisk socket client **
10 \*****************************************************************************/
16 To connect, open a socket and send a MESSAGE_HELLO to admin socket with
17 the application name. This name is unique an can be used for routing calls.
19 To make a call, send a MESSAGE_NEWREF and a new reference is received.
20 When receiving a call, a new reference is received.
21 The reference is received with MESSAGE_NEWREF.
23 Make a MESSAGE_SETUP or receive a MESSAGE_SETUP with the reference.
25 To release call and reference, send or receive MESSAGE_RELEASE.
26 From that point on, the ref is not valid, so no other message may be sent
36 #include <sys/types.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
45 #include <semaphore.h>
47 #include "extension.h"
49 #include "lcrsocket.h"
56 #include <asterisk/module.h>
57 #include <asterisk/channel.h>
58 #include <asterisk/config.h>
59 #include <asterisk/logger.h>
60 #include <asterisk/pbx.h>
61 #include <asterisk/options.h>
62 #include <asterisk/io.h>
63 #include <asterisk/frame.h>
64 #include <asterisk/translate.h>
65 #include <asterisk/cli.h>
66 #include <asterisk/musiconhold.h>
67 #include <asterisk/dsp.h>
68 #include <asterisk/translate.h>
69 #include <asterisk/file.h>
70 #include <asterisk/callerid.h>
71 #include <asterisk/indications.h>
72 #include <asterisk/app.h>
73 #include <asterisk/features.h>
74 #include <asterisk/sched.h>
83 struct admin_list *next;
85 } *admin_first = NULL;
88 * channel and call instances
90 struct chan_call *call_first;
92 struct chan_call *find_call_ref(unsigned long ref)
94 struct chan_call *call = call_first;
105 struct chan_call *find_call_handle(unsigned long handle)
107 struct chan_call *call = call_first;
111 if (call->bchannel_handle == handle)
118 struct chan_call *alloc_call(void)
120 struct chan_call **callp = &call_first;
123 callp = &((*callp)->next);
125 *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
129 void free_call(struct chan_call *call)
131 struct chan_call **temp = &call_first;
137 *temp = (*temp)->next;
141 temp = &((*temp)->next);
145 unsigned short new_brige_id(void)
147 struct chan_call *call;
148 unsigned short id = 1;
150 /* search for lowest bridge id that is not in use and not 0 */
156 if (call->bridge_id == id)
169 * receive bchannel data
171 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
175 void rx_dtmf(struct bchannel *bchannel, char tone)
180 * enque message to LCR
182 int send_message(int message_type, unsigned long ref, union parameter *param)
184 struct admin_list *admin, **adminp;
186 adminp = &admin_first;
188 adminp = &((*adminp)->next);
189 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
192 admin->msg.type = message_type;
193 admin->msg.ref = ref;
194 memcpy(&admin->msg.param, param, sizeof(union parameter));
200 * message received from LCR
202 int receive_message(int message_type, unsigned long ref, union parameter *param)
204 union parameter newparam;
205 struct bchannel *bchannel;
206 struct chan_call *call;
208 memset(&newparam, 0, sizeof(union parameter));
210 /* handle bchannel message*/
211 if (message_type == MESSAGE_BCHANNEL)
213 switch(param->bchannel.type)
215 case BCHANNEL_ASSIGN:
216 if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
218 fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
221 /* create bchannel */
222 bchannel = alloc_bchannel(param->bchannel.handle);
225 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
229 /* configure channel */
230 bchannel->b_tx_gain = param->bchannel.tx_gain;
231 bchannel->b_rx_gain = param->bchannel.rx_gain;
232 strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
233 if (param->bchannel.crypt_len)
235 bchannel->b_crypt_len = param->bchannel.crypt_len;
236 bchannel->b_crypt_type = param->bchannel.crypt_type;
237 memcpy(bchannel->b_crypt_key, param->bchannel.crypt, param->bchannel.crypt_len);
239 bchannel->b_txdata = 0;
240 bchannel->b_dtmf = 1;
241 bchannel->b_tx_dejitter = 1;
243 /* in case, ref is not set, this bchannel instance must
244 * be created until it is removed again by LCR */
246 if ((call = find_call_ref(ref)))
249 call->bchannel_handle = param->bchannel.handle;
250 #warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
251 bchannel_join(bchannel, call->bridge_id);
253 if (bchannel_create(bchannel))
254 bchannel_activate(bchannel, 1);
257 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
258 newparam.bchannel.handle = param->bchannel.handle;
259 send_message(MESSAGE_BCHANNEL, 0, &newparam);
262 case BCHANNEL_REMOVE:
263 if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
265 #warning alle fprintf nach ast_log
266 fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
269 /* unlink from call */
270 if ((call = find_call_ref(bchannel->ref)))
272 call->bchannel_handle = 0;
274 /* destroy and remove bchannel */
275 free_bchannel(bchannel);
278 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
279 newparam.bchannel.handle = param->bchannel.handle;
280 send_message(MESSAGE_BCHANNEL, 0, &newparam);
285 fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
291 if (message_type == MESSAGE_NEWREF)
293 if (param->direction)
295 /* new ref from lcr */
296 if (!ref || find_call_ref(ref))
298 fprintf(stderr, "illegal new ref %d received\n", ref);
305 /* new ref, as requested from this remote application */
306 call = find_call_ref(0);
309 /* send release, if ref does not exist */
310 newparam.disconnectinfo.cause = CAUSE_NORMAL;
311 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
312 send_message(MESSAGE_RELEASE, ref, &newparam);
316 #warning process call (send setup, if pending)
324 fprintf(stderr, "received message %d without ref\n", message_type);
327 call = find_call_ref(ref);
330 /* ignore ref that is not used (anymore) */
334 /* handle messages */
341 case MESSAGE_OVERLAP:
345 case MESSAGE_PROCEEDING:
349 case MESSAGE_ALERTING:
353 case MESSAGE_CONNECT:
357 case MESSAGE_DISCONNECT:
361 case MESSAGE_RELEASE:
366 case MESSAGE_INFORMATION:
370 case MESSAGE_FACILITY:
374 case MESSAGE_PATTERN:
378 case MESSAGE_NOPATTERN:
382 case MESSAGE_AUDIOPATH:
394 * warning! not thread safe
395 * returns -1 for socket error, 0 for no work, 1 for work
397 int handle_socket(void)
401 struct admin_message msg;
402 struct admin_list *admin;
406 #warning SOCKET FEHLT!
407 /* read from socket */
408 len = read(sock, &msg, sizeof(msg));
411 printf("Socket closed\n");
412 return(-1); // socket closed
416 if (len != sizeof(msg))
418 fprintf(stderr, "Socket short read (%d)\n", len);
419 return(-1); // socket error
421 if (msg.message != ADMIN_MESSAGE)
423 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
424 return(-1); // socket error
426 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
427 printf("message received %d\n", msg.u.msg.type);
431 if (errno != EWOULDBLOCK)
433 fprintf(stderr, "Socket error %d\n", errno);
438 /* write to socket */
442 len = write(sock, &admin->msg, sizeof(msg));
445 printf("Socket closed\n");
446 return(-1); // socket closed
450 if (len != sizeof(msg))
452 fprintf(stderr, "Socket short write (%d)\n", len);
453 return(-1); // socket error
456 admin_first = admin->next;
462 if (errno != EWOULDBLOCK)
464 fprintf(stderr, "Socket error %d\n", errno);
473 * open and close socket
475 int open_socket(void)
479 char *socket_name = SOCKET_NAME;
481 struct sockaddr_un sock_address;
482 unsigned long on = 1;
483 union parameter param;
486 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
488 ast_log(LOG_ERROR, "Failed to create socket.\n");
492 /* set socket address and name */
493 memset(&sock_address, 0, sizeof(sock_address));
494 sock_address.sun_family = PF_UNIX;
495 strcpy(sock_address.sun_path, socket_name);
498 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
501 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
505 /* set non-blocking io */
506 if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
509 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
513 /* enque hello message */
514 memset(¶m, 0, sizeof(param));
515 strcpy(param.hello.application, "asterisk");
516 send_message(MESSAGE_HELLO, 0, ¶m);
521 void close_socket(int sock)
529 void lcr_thread(void)
538 int ret = handle_socket();
545 ret = bchannel_handle();
554 static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
560 /* call from asterisk (new instance) */
561 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
563 struct lcr_pvt *lcr=ast->tech_pvt;
568 char *port_str, *dad, *p;
570 ast_copy_string(buf, dest, sizeof(buf)-1);
572 port_str=strsep(&p, "/");
576 ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
582 static int lcr_answer(struct ast_channel *c)
584 struct lcr_pvt *lcr=c->tech_pvt;
588 static int lcr_hangup(struct ast_channel *c)
590 struct lcr_pvt *lcr=c->tech_pvt;
595 static int lcr_write(struct ast_channel *c, struct ast_frame *f)
597 struct lcr_pvt *lcrm= c->tech_pvt;
601 static struct ast_frame *lcr_read(struct ast_channel *c)
603 struct lcr_pvt *lcr = c->tech_pvt;
606 static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
611 case AST_CONTROL_BUSY:
612 case AST_CONTROL_CONGESTION:
613 case AST_CONTROL_RINGING:
618 case AST_CONTROL_VIDUPDATE:
621 case AST_CONTROL_HOLD:
622 ast_verbose(" << Console Has Been Placed on Hold >> \n");
623 //ast_moh_start(c, data, g->mohinterpret);
625 case AST_CONTROL_UNHOLD:
626 ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
631 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
638 static struct ast_channel_tech lcr_tech = {
640 .description="Channel driver for connecting to Linux-Call-Router",
641 .capabilities=AST_FORMAT_ALAW,
642 .requester=lcr_request,
643 // .send_digit=lcr_digit,
645 // .bridge=lcr_bridge,
650 .indicate=lcr_indicate,
652 // .send_text=lcr_send_text,
659 static int cli_show_lcr (int fd, int argc, char *argv[])
663 static int cli_show_calls (int fd, int argc, char *argv[])
667 static int cli_reload_routing (int fd, int argc, char *argv[])
671 static int cli_reload_interfaces (int fd, int argc, char *argv[])
675 static int cli_port_block (int fd, int argc, char *argv[])
679 static int cli_port_unblock (int fd, int argc, char *argv[])
683 static int cli_port_unload (int fd, int argc, char *argv[])
687 static struct ast_cli_entry cli_show_lcr =
688 { {"lcr", "show", "lcr", NULL},
690 "Shows current states of LCR core",
691 "Usage: lcr show lcr\n",
694 static struct ast_cli_entry cli_show_calls =
695 { {"lcr", "show", "calls", NULL},
697 "Shows current calls made by LCR and Asterisk",
698 "Usage: lcr show calls\n",
701 static struct ast_cli_entry cli_reload_routing =
702 { {"lcr", "reload", "routing", NULL},
704 "Reloads routing conf of LCR, current uncomplete calls will be disconnected",
705 "Usage: lcr reload routing\n",
708 static struct ast_cli_entry cli_reload_interfaces =
709 { {"lcr", "reload", "interfaces", NULL},
710 lcr_reload_interfaces,
711 "Reloads interfaces conf of LCR",
712 "Usage: lcr reload interfaces\n",
715 static struct ast_cli_entry cli_port_block =
716 { {"lcr", "port", "block", NULL},
718 "Blocks LCR port for further calls",
719 "Usage: lcr port block \"<port>\"\n",
722 static struct ast_cli_entry cli_port_unblock =
723 { {"lcr", "port", "unblock", NULL},
725 "Unblocks or loads LCR port, port is opened my mISDN",
726 "Usage: lcr port unblock \"<port>\"\n",
729 static struct ast_cli_entry cli_port_unload =
730 { {"lcr", "port", "unload", NULL},
732 "Unloads LCR port, port is closes by mISDN",
733 "Usage: lcr port unload \"<port>\"\n",
738 * module loading and destruction
740 int load_module(void)
742 // ast_mutex_init(&release_lock);
744 // lcr_cfg_update_ptp();
746 if (!(lcr_sock = open_socket())) {
747 ast_log(LOG_ERROR, "Unable to connect\n");
749 /* continue with closed socket */
752 if (!bchannel_initialize()) {
753 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
758 if (ast_channel_register(&lcr_tech)) {
759 ast_log(LOG_ERROR, "Unable to register channel class\n");
764 ast_cli_register(&cli_show_lcr);
765 ast_cli_register(&cli_show_calls);
767 ast_cli_register(&cli_reload_routing);
768 ast_cli_register(&cli_reload_interfaces);
769 ast_cli_register(&cli_port_block);
770 ast_cli_register(&cli_port_unblock);
771 ast_cli_register(&cli_port_unload);
773 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
774 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
775 "Sets mISDN opts. and optargs\n"
777 "The available options are:\n"
778 " d - Send display text on called phone, text is the optparam\n"
779 " n - don't detect dtmf tones on called channel\n"
780 " h - make digital outgoing call\n"
781 " c - make crypted outgoing call, param is keyindex\n"
782 " e - perform echo cancelation on this channel,\n"
783 " takes taps as arguments (32,64,128,256)\n"
784 " s - send Non Inband DTMF as inband\n"
785 " vr - rxgain control\n"
786 " vt - txgain control\n"
790 lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
792 chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
794 //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
800 int unload_module(void)
802 /* First, take us out of the channel loop */
803 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
806 ast_channel_unregister(&lcr_tech);
809 bchannel_deinitialize();
821 static int reload_module(void)
828 ast_mutex_t usecnt_lock;
834 ast_mutex_lock(&usecnt_lock);
836 ast_mutex_unlock(&usecnt_lock);
841 char *desc="Channel driver for lcr";
843 char *description(void)
850 return ASTERISK_GPL_KEY;
853 #define AST_MODULE "chan_lcr"
854 AST_MODULE_INFO(ASTERISK_GPL_KEY,
856 "Channel driver for lcr",
858 .unload = unload_module,
859 .reload = reload_module,