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>
43 #include "extension.h"
53 struct admin_list *next;
55 } *admin_first = NULL;
58 * channel and call instances
60 struct chan_call *call_first;
62 struct chan_call *find_call_ref(unsigned long ref)
64 struct chan_call *call = call_first;
75 struct chan_call *find_call_handle(unsigned long handle)
77 struct chan_call *call = call_first;
81 if (call->bchannel_handle == handle)
88 struct chan_call *alloc_call(void)
90 struct chan_call **callp = &call_first;
93 callp = &((*callp)->next);
95 *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
99 void free_call(struct chan_call *call)
101 struct chan_call **temp = &call_first;
107 *temp = (*temp)->next;
111 temp = &((*temp)->next);
117 * receive bchannel data
119 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
123 void rx_dtmf(struct bchannel *bchannel, char tone)
128 * enque message to LCR
130 int send_message(int message_type, unsigned long ref, union parameter *param)
132 struct admin_list *admin, **adminp;
134 adminp = &admin_first;
136 adminp = &((*adminp)->next);
137 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
140 admin->msg.type = message_type;
141 admin->msg.ref = ref;
142 memcpy(&admin->msg.param, param, sizeof(union parameter));
148 * message received from LCR
150 int receive_message(int message_type, unsigned long ref, union parameter *param)
152 union parameter newparam;
153 struct bchannel *bchannel;
154 struct chan_call *call;
156 memset(&newparam, 0, sizeof(union parameter));
158 /* handle bchannel message*/
159 if (message_type == MESSAGE_BCHANNEL)
161 switch(param->bchannel.type)
163 case BCHANNEL_ASSIGN:
164 if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
166 fprintf(stderr, "error: bchannel handle %x already assigned.\n", param->bchannel.handle);
169 /* create bchannel */
170 bchannel = alloc_bchannel(param->bchannel.handle);
173 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", param->bchannel.handle);
177 /* configure channel */
178 bchannel->b_tx_gain = param->bchannel.tx_gain;
179 bchannel->b_rx_gain = param->bchannel.rx_gain;
180 strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
181 if (param->bchannel.crypt_len)
183 bchannel->b_crypt_len = param->bchannel.crypt_len;
184 bchannel->b_crypt_type = param->bchannel.crypt_type;
185 memcpy(bchannel->b_crypt_key, param->bchannel.crypt, param->bchannel.crypt_len);
187 bchannel->b_txdata = 0;
188 bchannel->b_dtmf = 1;
189 bchannel->b_tx_dejitter = 1;
191 /* in case, ref is not set, this bchannel instance must
192 * be created until it is removed again by LCR */
194 if ((call = find_call_ref(ref)))
197 call->bchannel_handle = param->bchannel.handle;
199 if (bchannel_create(bchannel))
200 bchannel_activate(bchannel, 1);
203 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
204 newparam.bchannel.handle = param->bchannel.handle;
205 send_message(MESSAGE_BCHANNEL, 0, &newparam);
208 case BCHANNEL_REMOVE:
209 if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
211 alle fprintf nach ast_log
212 fprintf(stderr, "error: bchannel handle %x not assigned.\n", param->bchannel.handle);
215 /* unlink from call */
216 if ((call = find_call_ref(bchannel->ref)))
218 call->bchannel_handle = 0;
220 /* destroy and remove bchannel */
221 free_bchannel(bchannel);
224 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
225 newparam.bchannel.handle = param->bchannel.handle;
226 send_message(MESSAGE_BCHANNEL, 0, &newparam);
231 fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
237 if (message_type == MESSAGE_NEWREF)
239 if (param->direction)
241 /* new ref from lcr */
242 if (!ref || find_call_ref(ref))
244 fprintf(stderr, "illegal new ref %d received\n", ref);
251 /* new ref, as requested from this remote application */
252 call = find_call_ref(0);
255 /* send release, if ref does not exist */
256 newparam.disconnectinfo.cause = CAUSE_NORMAL;
257 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
258 send_message(MESSAGE_RELEASE, ref, &newparam);
262 #warning process call (send setup, if pending)
270 fprintf(stderr, "received message %d without ref\n", message_type);
273 call = find_call_ref(ref);
276 /* ignore ref that is not used (anymore) */
280 /* handle messages */
287 case MESSAGE_OVERLAP:
291 case MESSAGE_PROCEEDING:
295 case MESSAGE_ALERTING:
299 case MESSAGE_CONNECT:
303 case MESSAGE_DISCONNECT:
307 case MESSAGE_RELEASE:
312 case MESSAGE_INFORMATION:
316 case MESSAGE_FACILITY:
320 case MESSAGE_PATTERN:
324 case MESSAGE_NOPATTERN:
328 case MESSAGE_AUDIOPATH:
340 * warning! not thread safe
341 * returns -1 for socket error, 0 for no work, 1 for work
343 int handle_socket(void)
347 struct admin_message msg;
348 struct admin_list *admin;
350 /* read from socket */
351 len = read(sock, &msg, sizeof(msg));
354 printf("Socket closed\n");
355 return(-1); // socket closed
359 if (len != sizeof(msg))
361 fprintf(stderr, "Socket short read (%d)\n", len);
362 return(-1); // socket error
364 if (msg.message != ADMIN_MESSAGE)
366 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
367 return(-1); // socket error
369 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
370 printf("message received %d\n", msg.u.msg.type);
374 if (errno != EWOULDBLOCK)
376 fprintf(stderr, "Socket error %d\n", errno);
381 /* write to socket */
385 len = write(sock, &admin->msg, sizeof(msg));
388 printf("Socket closed\n");
389 return(-1); // socket closed
393 if (len != sizeof(msg))
395 fprintf(stderr, "Socket short write (%d)\n", len);
396 return(-1); // socket error
399 admin_first = admin->next;
405 if (errno != EWOULDBLOCK)
407 fprintf(stderr, "Socket error %d\n", errno);
416 * open and close socket
418 int open_socket(void)
422 char *socket_name = SOCKET_NAME;
424 struct sockaddr_un sock_address;
426 unsigned long on = 1;
427 union parameter param;
430 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
432 ast_log(LOG_ERROR, "Failed to create socket.\n");
436 /* set socket address and name */
437 memset(&sock_address, 0, sizeof(sock_address));
438 sock_address.sun_family = PF_UNIX;
439 strcpy(sock_address.sun_path, socket_name);
442 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
445 ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
449 /* set non-blocking io */
450 if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
453 ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
457 /* enque hello message */
458 memset(¶m, 0, sizeof(param));
459 strcpy(param.hello.application, "asterisk");
460 send_message(MESSAGE_HELLO, 0, ¶m);
465 void close_socket(int sock)
473 void lcr_thread(void)
482 ret = handle_socket();
489 ret = bchannel_handle();
498 static struct ast_channel_tech misdn_tech = {
500 .description="Channel driver for connecting to Linux-Call-Router",
501 .capabilities= je nach option?AST_FORMAT_ALAW:AST_FORMAT_ULAW ,
502 .requester=lcr_request,
503 .send_digit=lcr_digit,
510 .indicate=lcr_indication,
512 .send_text=lcr_send_text,
518 * module loading and destruction
520 int load_module(void)
522 // ast_mutex_init(&release_lock);
524 // lcr_cfg_update_ptp();
526 if (!(lcr_sock = open_socket())) {
527 ast_log(LOG_ERROR, "Unable to connect %s\n", misdn_type);
529 /* continue with closed socket */
532 if (!bchannel_initialize()) {
533 ast_log(LOG_ERROR, "Unable to open mISDN device\n");
539 if (ast_channel_register(&lcr_tech)) {
540 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
545 ast_cli_register(&cli_show_cls);
546 ast_cli_register(&cli_show_cl);
547 ast_cli_register(&cli_show_config);
549 ast_cli_register(&cli_reload);
552 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
553 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
554 "Sets mISDN opts. and optargs\n"
556 "The available options are:\n"
557 " d - Send display text on called phone, text is the optparam\n"
558 " n - don't detect dtmf tones on called channel\n"
559 " h - make digital outgoing call\n"
560 " c - make crypted outgoing call, param is keyindex\n"
561 " e - perform echo cancelation on this channel,\n"
562 " takes taps as arguments (32,64,128,256)\n"
563 " s - send Non Inband DTMF as inband\n"
564 " vr - rxgain control\n"
565 " vt - txgain control\n"
569 lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
571 chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
576 int unload_module(void)
578 /* First, take us out of the channel loop */
579 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
581 misdn_tasks_destroy();
583 if (!g_config_initialized) return 0;
585 ast_cli_unregister(&cli_show_cls);
586 ast_cli_unregister(&cli_show_cl);
587 ast_cli_unregister(&cli_show_config);
588 ast_cli_unregister(&cli_reload);
589 ast_unregister_application("misdn_set_opt");
591 ast_channel_unregister(&lcr_tech);
594 bchannel_deinitialize();
603 was ist mit dem mutex
618 ast_mutex_lock(&usecnt_lock);
620 ast_mutex_unlock(&usecnt_lock);
624 char *description(void)
631 return ASTERISK_GPL_KEY;