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 fprintf(stderr, "error: bchannel handle %x not assigned.\n", param->bchannel.handle);
214 /* unlink from call */
215 if ((call = find_call_ref(bchannel->ref)))
217 call->bchannel_handle = 0;
219 /* destroy and remove bchannel */
220 free_bchannel(bchannel);
223 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
224 newparam.bchannel.handle = param->bchannel.handle;
225 send_message(MESSAGE_BCHANNEL, 0, &newparam);
230 fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
236 if (message_type == MESSAGE_NEWREF)
238 if (param->direction)
240 /* new ref from lcr */
241 if (!ref || find_call_ref(ref))
243 fprintf(stderr, "illegal new ref %d received\n", ref);
250 /* new ref, as requested from this remote application */
251 call = find_call_ref(0);
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);
261 #warning process call (send setup, if pending)
269 fprintf(stderr, "received message %d without ref\n", message_type);
272 call = find_call_ref(ref);
275 /* ignore ref that is not used (anymore) */
279 /* handle messages */
282 #warning we must see if ref is a reply or a request, do we??
283 case MESSAGE_RELEASE:
284 #warning release call
289 #warning handle incoming setup, send to asterisk
297 * warning! not thread safe
298 * returns -1 for socket error, 0 for no work, 1 for work
300 int handle_socket(void)
304 struct admin_message msg;
305 struct admin_list *admin;
307 /* read from socket */
308 len = read(sock, &msg, sizeof(msg));
311 printf("Socket closed\n");
312 return(-1); // socket closed
316 if (len != sizeof(msg))
318 fprintf(stderr, "Socket short read (%d)\n", len);
319 return(-1); // socket error
321 if (msg.message != ADMIN_MESSAGE)
323 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
324 return(-1); // socket error
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);
331 if (errno != EWOULDBLOCK)
333 fprintf(stderr, "Socket error %d\n", errno);
338 /* write to socket */
342 len = write(sock, &admin->msg, sizeof(msg));
345 printf("Socket closed\n");
346 return(-1); // socket closed
350 if (len != sizeof(msg))
352 fprintf(stderr, "Socket short write (%d)\n", len);
353 return(-1); // socket error
356 admin_first = admin->next;
362 if (errno != EWOULDBLOCK)
364 fprintf(stderr, "Socket error %d\n", errno);
375 int main(int argc, char *argv[])
377 char *socket_name = SOCKET_NAME;
379 struct sockaddr_un sock_address;
381 unsigned long on = 1;
382 union parameter param;
386 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
388 fprintf(stderr, "Failed to create socket.\n");
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);
398 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
401 fprintf(stderr, "Failed to connect to socket \"%s\".\nIs LCR running?\n", sock_address.sun_path);
405 /* set non-blocking io */
406 if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0)
409 fprintf(stderr, "Failed to set socket into non-blocking IO.\n");
413 /* enque hello message */
414 memset(¶m, 0, sizeof(param));
415 strcpy(param.hello.application, "asterisk");
416 send_message(MESSAGE_HELLO, 0, ¶m);
419 if (!bchannel_initialize())
420 goto bchannel_failed;
427 ret = handle_socket();
434 ret = bchannel_handle();
442 bchannel_deinitialize();
447 /* now we say good bye */