x86-64 compile fixes and cleanups
[asterisk/asterisk.git] / pbx / pbx_wilcalu.c
1 /** @file pbx_wilcalu.c 
2  *
3  * Asterisk -- A telephony toolkit for Linux.
4  *
5  * Trivial application to playback a sound file
6  * 
7  * Copyright (C) 1999, Mark Spencer
8  *
9  * Mark Spencer <markster@linux-support.net>
10  *
11  * This program is free software, distributed under the terms of
12  * the GNU General Public License
13
14  *  Autodialer for Asterisk 
15  *  Redirect dialstring thru fifo "/var/run/autodial.ctl"
16  *  Format of string is :
17  *  "tech/tele,filename&" ie. "tor1/23,file&"
18  */
19  
20 #include <asterisk/lock.h>
21 #include <asterisk/file.h>
22 #include <asterisk/logger.h>
23 #include <asterisk/channel.h>
24 #include <asterisk/pbx.h>
25 #include <asterisk/module.h>
26 #include <asterisk/translate.h>
27 #include <asterisk/options.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <pthread.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include "../astconf.h"
36
37
38 // Globals
39 const   char dialfile[255];
40 static  char *tdesc = "Wil Cal U (Auto Dialer)";
41 static  pthread_t autodialer_thread;
42 static  char buf[257];
43 static  char lastbuf[257];//contains last partial buffer
44 static  char sendbuf[257];
45 STANDARD_LOCAL_USER;
46 LOCAL_USER_DECL;
47
48 //prototype
49 static void *dialstring(void *string);
50
51 // types
52 struct alarm_data {
53 time_t alarm_time;
54 int    snooze_len;
55 void   *dialstr;
56 };
57
58 static void *autodial(void *ignore)
59 {
60         pthread_t dialstring_thread;
61         char * sendbufptr=sendbuf;
62         int fd=open(dialfile,O_RDONLY|O_NONBLOCK);
63         int flags = fcntl(fd, F_GETFL);
64         struct pollfd fds[1];
65         fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
66         if (option_debug)
67                 ast_log(LOG_DEBUG, "Entered Wil-Calu fd=%d\n",fd);
68         if(fd<0) {
69                 ast_log(LOG_WARNING, "Autodial: Unable to open file\n");
70                 pthread_exit(NULL);
71         }
72         memset(buf,0,257);
73         memset(lastbuf,0,257);
74         memset(sendbuf,0,257);
75         while(1){
76                 ssize_t bytes;
77                 void *pass;
78
79                 memset(buf,0,257);
80                 fds[0].fd = fd;
81                 fds[0].events = POLLIN;
82                 poll(fds, 1, -1);
83                 bytes=read(fd,buf,256);
84                 buf[(int)bytes]=0;
85
86                 if(bytes>0){
87                         int x;
88                         ast_log(LOG_DEBUG, "WilCalu : Read Buf %s\n",buf);
89                         sendbufptr=sendbuf;
90                         for(x=0;lastbuf[x]!=0 && x<257;x++);
91                         if(x) {
92                                 memcpy(sendbuf,lastbuf,x);
93                                 sendbufptr+=x;
94                                 memset(lastbuf,0,257);
95                         }
96                         /* Process bytes read */
97                         for(x=0;x<bytes;x++){
98                                 /* if & then string is complete */
99                                 if(buf[x]=='&'){
100                                         if(NULL!=(pass=(void *)strdup(sendbuf))){
101                                                 pthread_create(&dialstring_thread,NULL,dialstring,pass);
102                                                 sendbufptr=sendbuf;
103                                                 memset(sendbuf,0,257);
104                                         }
105                                         else {
106                                                 perror("Autodial:Strdup failed");
107                                                 close(fd);
108                                                 pthread_exit(NULL);
109                                         }
110                                 } else {
111                                         if(buf[x]=='\n')
112                                                 continue;
113                                         *sendbufptr=buf[x];
114                                         sendbufptr++;
115                                         *sendbufptr=0;
116                                 }
117                         }
118                         if(sendbufptr!=sendbuf)
119                                 memcpy(lastbuf,sendbuf,sendbufptr-sendbuf+1);
120                 }
121         }
122         close(fd);
123         pthread_exit(NULL);
124         return NULL;
125 }
126
127 static void *snooze_alarm(void *pass){
128         
129         pthread_t dialstring_thread;
130         struct alarm_data *data=(struct alarm_data *)pass;
131         sleep(data->snooze_len);
132         pthread_create(&dialstring_thread,NULL,dialstring,data->dialstr);
133         // dialstring will free data->dialstr
134         free(pass);
135         pthread_exit(NULL);
136         return NULL;
137 }
138 static void  set_snooze_alarm(char *dialstr,int snooze_len){
139         pthread_t snooze_alarm_thread;
140         struct alarm_data *pass;
141         ast_log(LOG_DEBUG, "Answered: Snooze Requested\n");
142         if(NULL==(pass=malloc(sizeof(struct alarm_data)))){
143                 perror("snooze_alarm: data");
144                 pthread_exit(NULL);
145         }
146         if(NULL==(pass->dialstr=(void *)strdup(dialstr))){
147                 free(pass);
148                 perror("snooze_alarm: dialstr");
149                 pthread_exit(NULL);
150         }
151         pass->snooze_len=snooze_len;
152         pthread_create(&snooze_alarm_thread,NULL,snooze_alarm,pass);
153 }
154                         
155 static void *dialstring(void *string){
156         struct ast_channel *channel;
157         char *bufptr,*destptr;
158         // ms affects number of rings
159         int  ms=10000;
160         int  cnt=0,first;
161         char tech[256];
162         char tele[256];
163         char filename[256];
164         int  answered=0;
165         for(first=0,bufptr=(char *)string,destptr=tech;*bufptr&&cnt<256;cnt++){
166                 if(*bufptr=='/' && !first){
167                         *destptr=0;
168                         destptr=tele;
169                         first=1;
170                 }
171                 else if(*bufptr==','){
172                         *destptr=0;
173                         destptr=filename;
174                 } else {
175                         *destptr=*bufptr;
176                         destptr++;
177                 }
178                 bufptr++;
179         } 
180         *destptr=0;
181         ast_log(LOG_DEBUG, "Printing string arg: %s Eos\n", (char *)string);
182         if(strlen(tech)+strlen(tele)+strlen(filename)>256){
183                 ast_log(LOG_ERROR, "Autodial:Error string too long\n");
184                 free(string);
185                 pthread_exit(NULL);
186         }
187         ast_log(LOG_DEBUG, "Autodial Tech %s(%d) Tele %s(%d) Filename %s(%d)\n",tech,(int)strlen(tech),tele,(int)strlen(tele),filename,(int)strlen(filename));
188
189         channel=ast_request(tech,AST_FORMAT_SLINEAR,tele);
190         if(channel!=NULL){
191                 ast_call(channel,tele,10000);
192         }
193         else {
194                 ast_log(LOG_ERROR, "Autodial:Sorry unable to obtain channel\n");
195                 free(string);
196                 pthread_exit(NULL);
197         }
198         if(channel->_state==AST_STATE_UP)
199                 ast_log(LOG_DEBUG, "Autodial:Line is Up\n");
200         while(ms>0){
201                 struct ast_frame *f;
202                 ms=ast_waitfor(channel,ms);
203                 f=ast_read(channel);
204                 if(!f){
205                         ast_log(LOG_DEBUG, "Autodial:Hung Up\n");
206                         break;
207                 }
208                 if(f->frametype==AST_FRAME_CONTROL){
209                         if(f->subclass==AST_CONTROL_ANSWER){
210                                 ast_log(LOG_DEBUG, "Autodial:Phone Answered\n");
211                                 if(channel->_state==AST_STATE_UP){
212                                         char res;
213                                         ast_streamfile(channel,filename,0);
214                                         // Press Five for snooze
215                                         res=ast_waitstream(channel, "37");
216                                         if(res=='3'){
217                                                 answered=1;
218                                                 set_snooze_alarm((char *)string,60);
219                                                 ast_streamfile(channel,"demo-thanks",0);
220                                                 ast_waitstream(channel, "");
221                                         }
222                                         else if(res=='7'){
223                                                 answered=1;
224                                                 ast_streamfile(channel,"demo-thanks",0);
225                                                 ast_waitstream(channel, "");
226                                         }
227                                         ast_stopstream(channel);
228                                         ms=0;
229                                 }
230                         }
231                         else if(f->subclass==AST_CONTROL_RINGING)
232                                 ast_log(LOG_DEBUG, "Autodial:Phone Ringing end\n");
233                 }
234                 ast_frfree(f);
235         }
236         if(!answered)
237                 set_snooze_alarm((char *)string,5);
238         free(string);
239         ast_hangup(channel);
240         ast_log(LOG_DEBUG, "Autodial:Hung up channel\n");
241         pthread_exit(NULL);
242         return NULL;
243 }
244 int unload_module(void)
245 {
246         STANDARD_HANGUP_LOCALUSERS;
247         unlink(dialfile);
248         return 0;
249 }
250
251 int load_module(void)
252 {
253         int val;
254         snprintf((char *)dialfile,sizeof(dialfile)-1,"%s/%s",(char *)ast_config_AST_RUN_DIR,"autodial.ctl");
255         if((val=mkfifo(dialfile, 0700))){
256                 if(errno!=EEXIST){
257                         ast_log(LOG_ERROR, "Error:%d Creating Autodial FIFO\n",errno);
258                         return 0;
259                 }
260         }
261         pthread_create(&autodialer_thread,NULL,autodial,NULL);
262         return 0;
263 }
264
265 char *description(void)
266 {
267         return tdesc;
268 }
269
270 int usecount(void)
271 {
272         int res;
273         STANDARD_USECOUNT(res);
274         return res;
275 }
276
277 char *key()
278 {
279         return ASTERISK_GPL_KEY;
280 }