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>
44 #include "extension.h"
54 struct admin_list *next;
56 } *admin_first = NULL;
59 * channel and call instances
61 struct chan_call *call_first;
63 struct chan_call *find_call_ref(unsigned long ref)
65 struct chan_call *call = call_first;
76 struct chan_call *find_call_handle(unsigned long handle)
78 struct chan_call *call = call_first;
82 if (call->bchannel_handle == handle)
89 struct chan_call *alloc_call(void)
91 struct chan_call **callp = &call_first;
94 callp = &((*callp)->next);
96 *callp = (struct chan_call *)MALLOC(sizeof(struct chan_call));
100 void free_call(struct chan_call *call)
102 struct chan_call **temp = &call_first;
108 *temp = (*temp)->next;
112 temp = &((*temp)->next);
118 * receive bchannel data
120 void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
124 void rx_dtmf(struct bchannel *bchannel, char tone)
129 * enque message to LCR
131 int send_message(int message_type, unsigned long ref, union parameter *param)
133 struct admin_list *admin, **adminp;
135 adminp = &admin_first;
137 adminp = &((*adminp)->next);
138 admin = (struct admin_list *)MALLOC(sizeof(struct admin_list));
141 admin->msg.type = message_type;
142 admin->msg.ref = ref;
143 memcpy(&admin->msg.param, param, sizeof(union parameter));
149 * message received from LCR
151 int receive_message(int message_type, unsigned long ref, union parameter *param)
153 union parameter newparam;
154 struct bchannel *bchannel;
155 struct chan_call *call;
157 memset(&newparam, 0, sizeof(union parameter));
159 /* handle bchannel message*/
160 if (message_type == MESSAGE_BCHANNEL)
162 switch(param->bchannel.type)
164 case BCHANNEL_ASSIGN:
165 if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
167 fprintf(stderr, "error: bchannel handle %x already assigned.\n", param->bchannel.handle);
170 /* create bchannel */
171 bchannel = alloc_bchannel(param->bchannel.handle);
174 fprintf(stderr, "error: alloc bchannel handle %x failed.\n", param->bchannel.handle);
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)
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);
188 bchannel->b_txdata = 0;
189 bchannel->b_dtmf = 1;
190 bchannel->b_tx_dejitter = 1;
192 /* in case, ref is not set, this bchannel instance must
193 * be created until it is removed again by LCR */
195 if ((call = find_call_ref(ref)))
198 call->bchannel_handle = param->bchannel.handle;
200 if (bchannel_create(bchannel))
201 bchannel_activate(bchannel, 1);
204 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
205 newparam.bchannel.handle = param->bchannel.handle;
206 send_message(MESSAGE_BCHANNEL, 0, &newparam);
209 case BCHANNEL_REMOVE:
210 if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
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 */
283 #warning we must see if ref is a reply or a request, do we??
284 case MESSAGE_RELEASE:
285 #warning release call
290 #warning handle incoming setup, send to asterisk
298 * warning! not thread safe
299 * returns -1 for socket error, 0 for no work, 1 for work
301 int handle_socket(void)
305 struct admin_message msg;
306 struct admin_list *admin;
308 /* read from socket */
309 len = read(sock, &msg, sizeof(msg));
312 printf("Socket closed\n");
313 return(-1); // socket closed
317 if (len != sizeof(msg))
319 fprintf(stderr, "Socket short read (%d)\n", len);
320 return(-1); // socket error
322 if (msg.message != ADMIN_MESSAGE)
324 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
325 return(-1); // socket error
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);
332 if (errno != EWOULDBLOCK)
334 fprintf(stderr, "Socket error %d\n", errno);
339 /* write to socket */
343 len = write(sock, &admin->msg, sizeof(msg));
346 printf("Socket closed\n");
347 return(-1); // socket closed
351 if (len != sizeof(msg))
353 fprintf(stderr, "Socket short write (%d)\n", len);
354 return(-1); // socket error
357 admin_first = admin->next;
363 if (errno != EWOULDBLOCK)
365 fprintf(stderr, "Socket error %d\n", errno);
376 int main(int argc, char *argv[])
378 char *socket_name = SOCKET_NAME;
380 struct sockaddr_un sock_address;
382 unsigned long on = 1;
383 union parameter param;
387 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
389 fprintf(stderr, "Failed to create socket.\n");
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);
399 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
402 fprintf(stderr, "Failed to connect to socket \"%s\".\nIs LCR running?\n", sock_address.sun_path);
406 /* set non-blocking io */
407 if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0)
410 fprintf(stderr, "Failed to set socket into non-blocking IO.\n");
414 /* enque hello message */
415 memset(¶m, 0, sizeof(param));
416 SCPY(param.hello.application, "asterisk");
417 send_message(MESSAGE_HELLO, 0, ¶m);
420 if (!bchannel_initialize())
421 goto bchannel_failed;
428 ret = handle_socket();
435 ret = bchannel_handle();
443 bchannel_deinitialize();
448 /* now we say good bye */