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"
47 #include "aserisk_client.h"
52 struct admin_list *next;
54 } *admin_first = NULL;
57 * enque message from asterisk
59 int send_message(int message_type, unsigned long ref, union parameter *param)
61 struct admin_list *admin, **adminp;
63 adminp = &admin_first;
65 adminp = &((*adminp)->next);
66 admin = (struct admin_list *)MALLOC(sizeof(struct admin_list));
69 admin->msg.type = message_type;
71 memcpy(&admin->msg.param, param, sizeof(union parameter));
77 * message received from LCR
79 int receive_message(int message_type, unsigned long ref, union parameter *param)
81 union parameter newparam;
83 memset(&newparam, 0, sizeof(union parameter));
85 /* handle bchannel message*/
86 if (message_type == MESSAGE_BCHANNEL)
88 switch(param.bchannel.type)
91 if (find_channel_addr(param->bchannel.addr))
93 fprintf(stderr, "error: bchannel addr %x already assigned.\n", param->bchannel.addr);
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;
103 if ((call = find_call_ref(param->bchannel.ref)))
105 call.addr = param->bchannel.addr;
110 newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
111 newparam.bchannel.addr = param->bchannel.addr;
112 send_message(MESSAGE_BCHANNEL, 0, &newparam);
115 case BCHANNEL_REMOVE:
116 if (!(channel = find_channel_addr(param->bchannel.addr)))
118 fprintf(stderr, "error: bchannel addr %x already assigned.\n", param->bchannel.addr);
121 /* unlink from call */
122 if ((call = find_call_ref(channel->ref)))
127 free_channel(channel);
130 newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
131 newparam.bchannel.addr = param->bchannel.addr;
132 send_message(MESSAGE_BCHANNEL, 0, &newparam);
137 fprintf(stderr, "received unknown bchannel message %d\n", param.bchannel.type);
147 * warning! not thread safe
148 * returns -1 for socket error, 0 for no work, 1 for work
150 int handle_socket(void)
154 struct admin_message msg;
155 struct admin_list *admin;
157 /* read from socket */
158 len = read(sock, &msg, sizeof(msg));
161 printf("Socket closed\n");
162 return(-1); // socket closed
166 if (len != sizeof(msg))
168 fprintf(stderr, "Socket short read (%d)\n", len);
169 return(-1); // socket error
171 if (msg.message != ADMIN_MESSAGE)
173 fprintf(stderr, "Socket received illegal message %d\n", msg.message);
174 return(-1); // socket error
176 receive_message(msg.type, msg.ref, &msg.param);
177 printf("message received %d\n", msg.u.msg.type);
181 if (errno != EWOULDBLOCK)
183 fprintf(stderr, "Socket error %d\n", errno);
188 /* write to socket */
192 len = write(sock, &admin->msg, sizeof(msg));
195 printf("Socket closed\n");
196 return(-1); // socket closed
200 if (len != sizeof(msg))
202 fprintf(stderr, "Socket short write (%d)\n", len);
203 return(-1); // socket error
206 admin_first = admin->next;
212 if (errno != EWOULDBLOCK)
214 fprintf(stderr, "Socket error %d\n", errno);
225 int main(int argc, char *argv[])
227 char *socket_name = SOCKET_NAME;
229 struct sockaddr_un sock_address;
231 unsigned long on = 1;
232 union parameter param;
235 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
237 fprintf(stderr, "Failed to create socket.\n");
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);
247 if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
250 fprintf(stderr, "Failed to connect to socket \"%s\".\nIs LCR running?\n", sock_address.sun_path);
254 /* set non-blocking io */
255 if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0)
258 fprintf(stderr, "Failed to set socket into non-blocking IO.\n");
262 /* enque hello message */
263 memset(¶m, 0, sizeof(param));
264 SCPY(param.hello.application, "asterisk");
265 admin_asterisk(MESSAGE_HELLO, ¶m);
269 ret = handle_socket();
278 /* now we say good bye */