work on asterisk channel driver
[lcr.git] / chan_lcr.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** Asterisk socket client                                                    **
9 **                                                                           **
10 \*****************************************************************************/
11
12 /*
13
14 How does it work:
15
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.
18
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.
22
23 Make a MESSAGE_SETUP or receive a MESSAGE_SETUP with the reference.
24
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
27 with that reference.
28
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdarg.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <time.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
42 #include <sys/un.h>
43 #include "extension.h"
44 #include "message.h"
45 #include "admin.h"
46 #include "cause.h"
47 #include "bchannel.h"
48 #include "chan_lcr.h"
49
50 int sock;
51
52 struct admin_list {
53         struct admin_list *next;
54         struct admin_msg msg;
55 } *admin_first = NULL;
56
57 /*
58  * channel and call instances
59  */
60 struct chan_call *call_first;
61
62 struct chan_call *find_call_ref(unsigned long ref)
63 {
64         struct chan_call *call = call_first;
65
66         while(call)
67         {
68                 if (call->ref == ref)
69                         break;
70                 call = call->next;
71         }
72         return(call);
73 }
74
75 struct chan_call *find_call_handle(unsigned long handle)
76 {
77         struct chan_call *call = call_first;
78
79         while(call)
80         {
81                 if (call->bchannel_handle == handle)
82                         break;
83                 call = call->next;
84         }
85         return(call);
86 }
87
88 struct chan_call *alloc_call(void)
89 {
90         struct chan_call **callp = &call_first;
91
92         while(*callp)
93                 callp = &((*callp)->next);
94
95         *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
96         return(*callp);
97 }
98
99 void free_call(struct chan_call *call)
100 {
101         struct chan_call **temp = &call_first;
102
103         while(*temp)
104         {
105                 if (*temp == call)
106                 {
107                         *temp = (*temp)->next;
108                         free(call);
109                         return;
110                 }
111                 temp = &((*temp)->next);
112         }
113 }
114
115
116 /*
117  * receive bchannel data
118  */
119 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
120 {
121 }
122
123 void rx_dtmf(struct bchannel *bchannel, char tone)
124 {
125 }
126
127 /*
128  * enque message to LCR
129  */
130 int send_message(int message_type, unsigned long ref, union parameter *param)
131 {
132         struct admin_list *admin, **adminp;
133
134         adminp = &admin_first;
135         while(*adminp)
136                 adminp = &((*adminp)->next);
137         admin = (struct admin_list *)malloc(sizeof(struct admin_list));
138         *adminp = admin;
139
140         admin->msg.type = message_type;
141         admin->msg.ref = ref;
142         memcpy(&admin->msg.param, param, sizeof(union parameter));
143
144         return(0);
145 }
146
147 /*
148  * message received from LCR
149  */
150 int receive_message(int message_type, unsigned long ref, union parameter *param)
151 {
152         union parameter newparam;
153         struct bchannel *bchannel;
154         struct chan_call *call;
155
156         memset(&newparam, 0, sizeof(union parameter));
157
158         /* handle bchannel message*/
159         if (message_type == MESSAGE_BCHANNEL)
160         {
161                 switch(param->bchannel.type)
162                 {
163                         case BCHANNEL_ASSIGN:
164                         if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
165                         {
166                                 fprintf(stderr, "error: bchannel handle %x already assigned.\n", param->bchannel.handle);
167                                 return(-1);
168                         }
169                         /* create bchannel */
170                         bchannel = alloc_bchannel(param->bchannel.handle);
171                         if (!bchannel)
172                         {
173                                 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", param->bchannel.handle);
174                                 return(-1);
175                         }
176
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)
182                         {
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);
186                         }
187                         bchannel->b_txdata = 0;
188                         bchannel->b_dtmf = 1;
189                         bchannel->b_tx_dejitter = 1;
190
191                         /* in case, ref is not set, this bchannel instance must
192                          * be created until it is removed again by LCR */
193                         /* link to call */
194                         if ((call = find_call_ref(ref)))
195                         {
196                                 bchannel->ref = ref;
197                                 call->bchannel_handle = param->bchannel.handle;
198                         }
199                         if (bchannel_create(bchannel))
200                                 bchannel_activate(bchannel, 1);
201
202                         /* acknowledge */
203                         newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
204                         newparam.bchannel.handle = param->bchannel.handle;
205                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
206                         break;
207
208                         case BCHANNEL_REMOVE:
209                         if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
210                         {
211                                 fprintf(stderr, "error: bchannel handle %x not assigned.\n", param->bchannel.handle);
212                                 return(-1);
213                         }
214                         /* unlink from call */
215                         if ((call = find_call_ref(bchannel->ref)))
216                         {
217                                 call->bchannel_handle = 0;
218                         }
219                         /* destroy and remove bchannel */
220                         free_bchannel(bchannel);
221
222                         /* acknowledge */
223                         newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
224                         newparam.bchannel.handle = param->bchannel.handle;
225                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
226                         
227                         break;
228
229                         default:
230                         fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
231                 }
232                 return(0);
233         }
234
235         /* handle new ref */
236         if (message_type == MESSAGE_NEWREF)
237         {
238                 if (param->direction)
239                 {
240                         /* new ref from lcr */
241                         if (!ref || find_call_ref(ref))
242                         {
243                                 fprintf(stderr, "illegal new ref %d received\n", ref);
244                                 return(-1);
245                         }
246                         call = alloc_call();
247                         call->ref = ref;
248                 } else
249                 {
250                         /* new ref, as requested from this remote application */
251                         call = find_call_ref(0);
252                         if (!call)
253                         {
254                                 /* send release, if ref does not exist */
255                                 newparam.disconnectinfo.cause = CAUSE_NORMAL;
256                                 newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
257                                 send_message(MESSAGE_RELEASE, ref, &newparam);
258                                 return(0);
259                         }
260                         call->ref = ref;
261 #warning process call (send setup, if pending)
262                 }
263                 return(0);
264         }
265
266         /* check ref */
267         if (!ref)
268         {
269                 fprintf(stderr, "received message %d without ref\n", message_type);
270                 return(-1);
271         }
272         call = find_call_ref(ref);
273         if (!call)
274         {
275                 /* ignore ref that is not used (anymore) */
276                 return(0);
277         }
278
279         /* handle messages */
280         switch(message_type)
281         {
282 #warning we must see if ref is a reply or a request, do we??
283                 case MESSAGE_RELEASE:
284 #warning release call
285                 free_call(call);
286                 return(0);
287
288                 case MESSAGE_SETUP:
289 #warning handle incoming setup, send to asterisk
290                 break;
291         }
292         return(0);
293 }
294
295
296 /* asterisk handler
297  * warning! not thread safe
298  * returns -1 for socket error, 0 for no work, 1 for work
299  */
300 int handle_socket(void)
301 {
302         int work = 0;
303         int len;
304         struct admin_message msg;
305         struct admin_list *admin;
306
307         /* read from socket */
308         len = read(sock, &msg, sizeof(msg));
309         if (len == 0)
310         {
311                 printf("Socket closed\n");
312                 return(-1); // socket closed
313         }
314         if (len > 0)
315         {
316                 if (len != sizeof(msg))
317                 {
318                         fprintf(stderr, "Socket short read (%d)\n", len);
319                         return(-1); // socket error
320                 }
321                 if (msg.message != ADMIN_MESSAGE)
322                 {
323                         fprintf(stderr, "Socket received illegal message %d\n", msg.message);
324                         return(-1); // socket error
325                 }
326                 receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
327                 printf("message received %d\n", msg.u.msg.type);
328                 work = 1;
329         } else
330         {
331                 if (errno != EWOULDBLOCK)
332                 {
333                         fprintf(stderr, "Socket error %d\n", errno);
334                         return(-1);
335                 }
336         }
337
338         /* write to socket */
339         if (!admin_first)
340                 return(work);
341         admin = admin_first;
342         len = write(sock, &admin->msg, sizeof(msg));
343         if (len == 0)
344         {
345                 printf("Socket closed\n");
346                 return(-1); // socket closed
347         }
348         if (len > 0)
349         {
350                 if (len != sizeof(msg))
351                 {
352                         fprintf(stderr, "Socket short write (%d)\n", len);
353                         return(-1); // socket error
354                 }
355                 /* free head */
356                 admin_first = admin->next;
357                 free(admin);
358
359                 work = 1;
360         } else
361         {
362                 if (errno != EWOULDBLOCK)
363                 {
364                         fprintf(stderr, "Socket error %d\n", errno);
365                         return(-1);
366                 }
367         }
368
369         return(work);
370 }
371
372 /*
373  * main function
374  */
375 int main(int argc, char *argv[])
376 {
377         char *socket_name = SOCKET_NAME;
378         int conn;
379         struct sockaddr_un sock_address;
380         int ret;
381         unsigned long on = 1;
382         union parameter param;
383         int work;
384
385         /* open socket */
386         if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
387         {
388                 fprintf(stderr, "Failed to create socket.\n");
389                 exit(EXIT_FAILURE);
390         }
391
392         /* set socket address and name */
393         memset(&sock_address, 0, sizeof(sock_address));
394         sock_address.sun_family = PF_UNIX;
395         strcpy(sock_address.sun_path, socket_name);
396
397         /* connect socket */
398         if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
399         {
400                 close(sock);
401                 fprintf(stderr, "Failed to connect to socket \"%s\".\nIs LCR running?\n", sock_address.sun_path);
402                 exit(EXIT_FAILURE);
403         }
404
405         /* set non-blocking io */
406         if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0)
407         {
408                 close(sock);
409                 fprintf(stderr, "Failed to set socket into non-blocking IO.\n");
410                 exit(EXIT_FAILURE);
411         }
412
413         /* enque hello message */
414         memset(&param, 0, sizeof(param));
415         strcpy(param.hello.application, "asterisk");
416         send_message(MESSAGE_HELLO, 0, &param);
417
418         /* bchannel */
419         if (!bchannel_initialize())
420                 goto bchannel_failed;
421         
422         while(42)
423         {
424                 work = 0;
425
426                 /* handle socket */
427                 ret = handle_socket();
428                 if (ret < 0)
429                         break;
430                 if (ret)
431                         work = 1;
432
433                 /* handle mISDN */
434                 ret = bchannel_handle();
435                 if (ret)
436                         work = 1;
437                 
438                 if (!work)
439                         usleep(30000);
440         }
441
442         bchannel_deinitialize();
443         bchannel_failed:
444         
445         /* close socket */      
446         close(sock);
447         /* now we say good bye */
448         if (ret)
449         {
450                 printf("%s\n", ret);
451                 exit(EXIT_FAILURE);
452         }
453 }
454
455
456
457
458