fix
[lcr.git] / asterisk_client.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 "aserisk_client.h"
48
49 int sock;
50
51 struct admin_list {
52         struct admin_list *next;
53         struct admin_msg msg;
54 } *admin_first = NULL;
55
56 /*
57  * enque message from asterisk
58  */
59 int send_message(int message_type, unsigned long ref, union parameter *param)
60 {
61         struct admin_list *admin, **adminp;
62
63         adminp = &admin_first;
64         while(*adminp)
65                 adminp = &((*adminp)->next);
66         admin = (struct admin_list *)MALLOC(sizeof(struct admin_list));
67         *adminp = admin;
68
69         admin->msg.type = message_type;
70         admin->msg.ref = ref;
71         memcpy(&admin->msg.param, param, sizeof(union parameter));
72
73         return(0);
74 }
75
76 /*
77  * message received from LCR
78  */
79 int receive_message(int message_type, unsigned long ref, union parameter *param)
80 {
81         union parameter newparam;
82
83         memset(&newparam, 0, sizeof(union parameter));
84
85         /* handle bchannel message*/
86         if (message_type == MESSAGE_BCHANNEL)
87         {
88                 switch(param.bchannel.type)
89                 {
90                         case BCHANNEL_ASSIGN:
91                         if (find_channel_addr(param->bchannel.addr))
92                         {
93                                 fprintf(stderr, "error: bchannel addr %x already assigned.\n", param->bchannel.addr);
94                                 return(-1);
95                         }
96                         /* create channel */
97                         channel = alloc_channel();
98                         channel.addr = param->bchannel.addr;
99                         /* in case, ref is not set, this channel instance must
100                          * be created until it is removed again by LCR */
101                         channel.ref = param->bchannel.ref;
102                         /* link to call */
103                         if ((call = find_call_ref(param->bchannel.ref)))
104                         {
105                                 call.addr = param->bchannel.addr;
106                         }
107
108 #warning open stack
109                         /* acknowledge */
110                         newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
111                         newparam.bchannel.addr = param->bchannel.addr;
112                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
113                         break;
114
115                         case BCHANNEL_REMOVE:
116                         if (!(channel = find_channel_addr(param->bchannel.addr)))
117                         {
118                                 fprintf(stderr, "error: bchannel addr %x already assigned.\n", param->bchannel.addr);
119                                 return(-1);
120                         }
121                         /* unlink from call */
122                         if ((call = find_call_ref(channel->ref)))
123                         {
124                                 call.addr = 0;
125                         }
126                         /* remove channel */
127                         free_channel(channel);
128 #warning close stack
129                         /* acknowledge */
130                         newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
131                         newparam.bchannel.addr = param->bchannel.addr;
132                         send_message(MESSAGE_BCHANNEL, 0, &newparam);
133                         
134                         break;
135
136                         default:
137                         fprintf(stderr, "received unknown bchannel message %d\n", param.bchannel.type);
138                 }
139                 return(0);
140         }
141         switch(message_type)
142         return(0);
143 }
144
145
146 /* asterisk handler
147  * warning! not thread safe
148  * returns -1 for socket error, 0 for no work, 1 for work
149  */
150 int handle_socket(void)
151 {
152         int work = 0;
153         int len;
154         struct admin_message msg;
155         struct admin_list *admin;
156
157         /* read from socket */
158         len = read(sock, &msg, sizeof(msg));
159         if (len == 0)
160         {
161                 printf("Socket closed\n");
162                 return(-1); // socket closed
163         }
164         if (len > 0)
165         {
166                 if (len != sizeof(msg))
167                 {
168                         fprintf(stderr, "Socket short read (%d)\n", len);
169                         return(-1); // socket error
170                 }
171                 if (msg.message != ADMIN_MESSAGE)
172                 {
173                         fprintf(stderr, "Socket received illegal message %d\n", msg.message);
174                         return(-1); // socket error
175                 }
176                 receive_message(msg.type, msg.ref, &msg.param);
177                 printf("message received %d\n", msg.u.msg.type);
178                 work = 1;
179         } else
180         {
181                 if (errno != EWOULDBLOCK)
182                 {
183                         fprintf(stderr, "Socket error %d\n", errno);
184                         return(-1);
185                 }
186         }
187
188         /* write to socket */
189         if (!admin_first)
190                 return(work);
191         admin = admin_first;
192         len = write(sock, &admin->msg, sizeof(msg));
193         if (len == 0)
194         {
195                 printf("Socket closed\n");
196                 return(-1); // socket closed
197         }
198         if (len > 0)
199         {
200                 if (len != sizeof(msg))
201                 {
202                         fprintf(stderr, "Socket short write (%d)\n", len);
203                         return(-1); // socket error
204                 }
205                 /* free head */
206                 admin_first = admin->next;
207                 FREE(admin, 0);
208
209                 work = 1;
210         } else
211         {
212                 if (errno != EWOULDBLOCK)
213                 {
214                         fprintf(stderr, "Socket error %d\n", errno);
215                         return(-1);
216                 }
217         }
218
219         return(work);
220 }
221
222 /*
223  * main function
224  */
225 int main(int argc, char *argv[])
226 {
227         char *socket_name = SOCKET_NAME;
228         int conn;
229         struct sockaddr_un sock_address;
230         int ret;
231         unsigned long on = 1;
232         union parameter param;
233
234         /* open socket */
235         if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
236         {
237                 fprintf(stderr, "Failed to create socket.\n");
238                 exit(EXIT_FAILURE);
239         }
240
241         /* set socket address and name */
242         memset(&sock_address, 0, sizeof(sock_address));
243         sock_address.sun_family = PF_UNIX;
244         UCPY(sock_address.sun_path, socket_name);
245
246         /* connect socket */
247         if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
248         {
249                 close(sock);
250                 fprintf(stderr, "Failed to connect to socket \"%s\".\nIs LCR running?\n", sock_address.sun_path);
251                 exit(EXIT_FAILURE);
252         }
253
254         /* set non-blocking io */
255         if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0)
256         {
257                 close(sock);
258                 fprintf(stderr, "Failed to set socket into non-blocking IO.\n");
259                 exit(EXIT_FAILURE);
260         }
261
262         /* enque hello message */
263         memset(&param, 0, sizeof(param));
264         SCPY(param.hello.application, "asterisk");
265         admin_asterisk(MESSAGE_HELLO, &param);
266
267         while(42)
268         {
269                 ret = handle_socket();
270                 if (ret < 0)
271                         break;
272                 if (!ret)
273                         usleep(30000);
274         }
275         
276         /* close socket */      
277         close(sock);
278         /* now we say good bye */
279         if (ret)
280         {
281                 printf("%s\n", ret);
282                 exit(EXIT_FAILURE);
283         }
284 }
285
286
287
288
289