From ravindra, 6 Years ago, written in Plain Text.
- view diff
Embed
  1. /**
  2.  *This code is developed to handle outboud socket requests from mod_inmate.
  3.  *USE: originate bleg and play prompt for callee on based of callee's reply in ivr either bridge call or hangup.
  4.  *     also handle hangup scenarios of bleg and aleg before bridging call.
  5.  *  
  6.  *      tab : 8
  7.  *      indent : 4
  8.  * */
  9.  
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <esl.h>
  14.  
  15. static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr, void *user_data)
  16. {
  17.         esl_handle_t handle = {{0}};
  18.         char cmd[512] = "";
  19.         int done = 0;
  20.         int set = 0;
  21.         esl_status_t status;
  22.         time_t exp = 0;
  23.         int prompt_Play = 0;    /* flag to check if prompt is played or not on bleg */
  24. /**
  25.  *Create a child process for each socket connection request
  26.  * */
  27.         if (fork()) {
  28.             return;
  29.         }
  30. /**
  31. *GET socket connection handle object
  32. * */   
  33.         if (esl_attach_handle(&handle, client_sock, addr) != ESL_SUCCESS) {
  34.             return;
  35.         }
  36.         esl_log(ESL_LOG_INFO, "Connected! %d\n", handle.sock);
  37. /**
  38.  *Filter all events for only one channel and get ani number,dst number,channel uuid,
  39.  *max_try,max_call_time and ring timeout values from channel
  40.  * */
  41.         esl_filter(&handle, "unique-id", esl_event_get_header(handle.info_event, "caller-unique-id"));
  42.         const char *ani = esl_event_get_header(handle.info_event, "caller-ani");
  43.         const char *dst = esl_event_get_header(handle.info_event, "caller-destination-number");
  44.         const char *uuid = esl_event_get_header(handle.info_event, "caller-unique-id");
  45.         const char *try = esl_event_get_header(handle.info_event, "variable_max_try");
  46.         const char *call_time = esl_event_get_header(handle.info_event, "variable_max_call_time");
  47.         const char *timeout = esl_event_get_header(handle.info_event, "variable_ring_timeout");
  48.         //esl_log(ESL_LOG_INFO, "HELLOOOOO  [%s]::::[%s]::::[%s]\n", ani,dst,uuid);
  49.        
  50.         esl_events(&handle, ESL_EVENT_TYPE_PLAIN, "SESSION_HEARTBEAT CHANNEL_ANSWER CHANNEL_HANGUP BACKGROUND_JOB CHANNEL_BRIDGE CHANNEL_EXECUTE CHANNEL_EXECUTE_COMPLETE DTMF"); /* select which events we want to get(subscribe) from freeswitch */
  51.         esl_send_recv(&handle, "linger"); /* Do not close socket even if channel is hungup wait till all channel events are completed.*/
  52. /**
  53.  *Originate bleg using API in background
  54.  * */
  55.         snprintf(cmd,sizeof(cmd),"bgapi call_bridge %s %s %s %s %s \n\n", ani, dst, uuid, try, timeout);
  56.         esl_send_recv(&handle,cmd);
  57.         //printf("%s\n", handle.last_sr_reply);
  58.         esl_execute(&handle, "sleep", "2000", NULL);
  59. /**
  60.  *recieve timed events (time_period:10sec)
  61.  * */
  62.         while((status = esl_recv_timed(&handle, 10000)) != ESL_FAIL) {
  63.             if (done) {
  64.                 if (time(NULL) >= exp) {
  65.                     break;
  66.                 }
  67.             } else if (status == ESL_SUCCESS) {
  68.                 const char *type = esl_event_get_header(handle.last_event, "content-type");
  69.                 if (type && !strcasecmp(type, "text/event-plain")) {
  70.                     const char *eventname = esl_event_get_header(handle.last_ievent, "event-name");
  71.                     esl_log(ESL_LOG_INFO, "########################################################################## %s.\n",eventname);
  72.                 /* *
  73.                  *Filter channel b events along with channel a events
  74.                  * */
  75.                     const char *bleg = esl_event_get_header(handle.last_ievent, "variable_bleg_uuid");
  76.                     if(set == 0 && bleg){
  77.                         esl_filter(&handle, "unique-id", bleg);
  78.                         set = 1;
  79.                     }
  80.                 /**
  81.                  *Handle DTMF event from b leg
  82.                  *
  83.                  *if 1 is pressed check if call_time is less than 120 play prompt on a leg
  84.                  *and set bleg_state as BRIDGE_CALL
  85.                  * */                          
  86.                     if( eventname && !strcasecmp(eventname, "DTMF")){
  87.                         const char *dtmf = esl_event_get_header(handle.last_ievent, "DTMF-Digit");
  88.                         if( dtmf && !strcasecmp(dtmf, "1")){
  89.                             printf("##################### CALL TIME ::::  %s %d\n", call_time,strcmp("120",call_time));
  90.                             if(strcmp("120",call_time) >= 0 ){
  91.                                 esl_execute(&handle, "playback", "/home/inmate_fs_data/sounds/en/less_than_2_min.wav", NULL);
  92.                                 prompt_Play = 1;
  93.                             }
  94.                             char bridge[100] = "";
  95.                             snprintf(bridge,sizeof(bridge),"api uuid_setvar %s bleg_state BRIDGE_CALL",uuid);
  96.                             esl_log(ESL_LOG_CRIT, "&&&&&&& ACCEPTED on bleg %s.\n",bridge);
  97.                             esl_send_recv(&handle,bridge);
  98.                             printf("%s\n", handle.last_sr_reply);
  99.                             if( prompt_Play == 0){ /* If prompt is not played disconnect socket */
  100.                                 done = 1;
  101.                                 break;
  102.                             }
  103.                         }
  104.                     }
  105.                 /* *
  106.                  * if prompt flag is set and prompt playing is over on leg a than disconnect socket
  107.                  * */
  108.                    if( eventname && !strcasecmp(eventname, "CHANNEL_EXECUTE_COMPLETE") ){
  109.                             //esl_log(ESL_LOG_CRIT, "&&&&&&&&&&&&&&&&&&&&&&& PROMPT PLAYING SET %s %d.\n",eventname,prompt_Play);
  110.                             const char *playback = esl_event_get_header(handle.last_ievent, "Application-Response");
  111.                             const char *leg_owner = esl_event_get_header(handle.last_ievent, "variable_owner");
  112.                             esl_log(ESL_LOG_CRIT, "&&&&&&&&&&&&&&&&&&&&&&& PROMPT PLAYING SET %s %s %s.\n",playback,leg_owner,bleg);
  113.                                 if( playback && !strcasecmp(playback, "FILE PLAYED") && ( prompt_Play == 1) ){
  114.                                     if( leg_owner  && bleg && !strcasecmp(leg_owner, "aleg")){
  115.                                         done =1;
  116.                                         break;
  117.                                     }
  118.                                 }
  119.                         }
  120.                 /*
  121.                 * Handle Hangup related events and set bleg state if bleg is hungup before bridge with its cause.
  122.                 **/
  123.                    if( eventname && !strcasecmp(eventname, "CHANNEL_HANGUP")){
  124.                             const char *owner = esl_event_get_header(handle.last_ievent, "variable_owner");
  125.                             //esl_log(ESL_LOG_INFO, "########################################################################## %s.\n",owner);
  126.                             if( owner  && bleg && !strcasecmp(owner, "aleg")){ /*if bleg is initiated and aleg is hungup than kill bleg channel*/
  127.                                 snprintf(cmd,sizeof(cmd),"api uuid_kill %s\n\n", bleg);
  128.                                 esl_log(ESL_LOG_CRIT, "&&&&&&& HANGUP RECIEVED on aleg %s.\n",cmd);
  129.                                 esl_send_recv(&handle,cmd);
  130.                                 printf("%s\n", handle.last_sr_reply);
  131.                             }else if(owner && !strcasecmp(owner, "bleg")){ /* Handle bleg hangup cases */
  132.                                 char *cause = esl_event_get_header(handle.last_ievent, "Hangup-Cause");
  133.                                 esl_log(ESL_LOG_CRIT, "&&&&&&& HANGUP RECIEVED on bleg. %s\n",cause);
  134.                                 if(cause && !strcasecmp(cause,"SUCCESS")){
  135.                                 /* if hangup cause is success check ivr read status if failure/num invalid set bleg-state to NOANSWER */
  136.                                     const char *read_status = esl_event_get_header(handle.last_ievent, "variable_read_result");
  137.                                     if( read_status && !strcasecmp(read_status,"failure")){
  138.                                         esl_log(ESL_LOG_CRIT, "&&&&&&& READ STATUS RECIEVED on bleg %s.\n",read_status);
  139.                                         cause = "NO_ANSWER";
  140.                                     }else if ( read_status && !strcasecmp(read_status,"success")){
  141.                                         const char *inv_num = esl_event_get_header(handle.last_ievent, "variable_num_invalid");
  142.                                         esl_log(ESL_LOG_CRIT, "&&&&&&& READ STATUS RECIEVED on bleg %s %s.\n",read_status,inv_num);
  143.                                         if( inv_num ){
  144.                                             esl_log(ESL_LOG_CRIT, "&&&&&&& READ STATUS INV RECIEVED on bleg %s.\n",read_status);
  145.                                             cause = "NO_ANSWER";
  146.                                         }
  147.                                    }   
  148.                                 }
  149.  
  150.                                 char state[100] = "";
  151.                                 snprintf(state,sizeof(state),"api uuid_setvar %s bleg_state %s",uuid,cause);
  152.                                 esl_log(ESL_LOG_CRIT, "&&&&&&& HANGUP RECIEVED on bleg %s.\n",state);
  153.                                 esl_send_recv(&handle,state);
  154.                                 printf("%s\n", handle.last_sr_reply);
  155.                                 done = 1;
  156.                                 break;
  157.                         }
  158.                     }  
  159.                 }
  160.             }
  161.         }
  162.                 esl_log(ESL_LOG_INFO, "Disconnected! %d\n", handle.sock);
  163.                 esl_disconnect(&handle);
  164. }
  165.  
  166. static esl_socket_t server_sock = ESL_SOCK_INVALID;
  167.  
  168. static void handle_sig(int sig)
  169. {
  170.         shutdown(server_sock, 2);
  171.  
  172. }
  173.  
  174. int main(void)
  175. {
  176.         signal(SIGINT, handle_sig);
  177.         signal(SIGCHLD, SIG_IGN);
  178.  
  179.         esl_global_set_default_logger(7);
  180.         esl_listen("localhost", 8040, mycallback, NULL, &server_sock);
  181.  
  182.         return 0;
  183. }
  184.