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