pbx_wilcalu.c 6.4 KB

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