2、mod_ccpaas.c

  1. #include <switch.h>  
  2. #include <switch_stun.h>  
  3.  
  4. #define zstr(x) _zstr(x)
  5.  
  6. SWITCH_MODULE_LOAD_FUNCTION(mod_ccpaas_load);
  7. SWITCH_MODULE_RUNTIME_FUNCTION(mod_ccpaas_runtime);
  8. SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_ccpaas_shutdown);
  9. SWITCH_MODULE_DEFINITION(mod_ccpaas, mod_ccpaas_load, mod_ccpaas_shutdown, mod_ccpaas_runtime);
  10.  
  11. switch_api_interface_t *api_interface;
  12.  
  13. static struct {
  14.     switch_hash_t *caller_orig_hash;
  15.     switch_hash_t *consumer_orig_hash;
  16.     switch_hash_t *bridge_hash;
  17.     switch_hash_t *use_hash;
  18.     switch_mutex_t *use_mutex;
  19.     switch_mutex_t *caller_orig_mutex;
  20.     switch_mutex_t *consumer_orig_mutex;
  21.     switch_mutex_t *bridge_mutex;
  22.     switch_hash_t *fifo_hash;
  23.     switch_mutex_t *mutex;
  24.     switch_mutex_t *sql_mutex;
  25.     switch_memory_pool_t *pool;
  26.     int running;
  27.     switch_event_node_t *node;
  28.     char hostname[256];
  29.     char *dbname;
  30.     char odbc_dsn[1024];
  31.     int node_thread_running;
  32.     switch_odbc_handle_t *master_odbc;
  33.     int threads;
  34.     switch_thread_t *node_thread;
  35.     int debug;
  36.     struct fifo_node *nodes;
  37.     char *pre_trans_execute;
  38.     char *post_trans_execute;
  39.     char *inner_pre_trans_execute;
  40.     char *inner_post_trans_execute;
  41.     switch_sql_queue_manager_t *qm;
  42.     int allow_transcoding;
  43.     switch_bool_t delete_all_members_on_startup;
  44. } globals;
  45.  
  46. struct callback {
  47.     char *buf;
  48.     size_t len;
  49.     int matches;
  50. };
  51. typedef struct callback callback_t;
  52. struct cc_paas_call_obj {
  53.     char aleg[64];
  54. char gateway[32];
  55.     char exten[64];
  56. char dp[32];
  57. char context[32];
  58. char cid_name[32];
  59. char cid_num[32];
  60. char number[15];
  61. char uid[32];
  62. char task_table[32];
  63. char task_tabke_id[32];
  64. switch_memory_pool_t *pool;
  65. };
  66.  
  67. switch_cache_db_handle_t *ccpaas_get_db_handle(void)
  68. {
  69.     switch_cache_db_handle_t *dbh = NULL;
  70.     char *dsn;
  71.  
  72.     if (!zstr(globals.odbc_dsn)) {
  73.         dsn = globals.odbc_dsn;
  74.     } else {
  75.         dsn = globals.dbname;
  76.     }
  77.  
  78.     if (switch_cache_db_get_db_handle_dsn(&dbh, dsn) != SWITCH_STATUS_SUCCESS) {
  79.         dbh = NULL;
  80.     }
  81.  
  82.     return dbh;
  83. }
  84.  
  85. static switch_bool_t ccpaas_execute_sql_callback(switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata)
  86. {
  87.     switch_bool_t ret = SWITCH_FALSE;
  88.     char *errmsg = NULL;
  89.     switch_cache_db_handle_t *dbh = NULL;
  90.  
  91.     if (mutex) {
  92.         switch_mutex_lock(mutex);
  93.     }
  94.  
  95.     if (!(dbh = ccpaas_get_db_handle())) {
  96.         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
  97.         goto end;
  98.     }
  99.  
  100.     if (globals.debug > 1) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "sql: %s\n", sql);
  101.  
  102.     switch_cache_db_execute_sql_callback(dbh, sql, callback, pdata, &errmsg);
  103.  
  104.     if (errmsg) {
  105.         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
  106.         free(errmsg);
  107.     }
  108.  
  109. end:
  110.  
  111.     switch_cache_db_release_db_handle(&dbh);
  112.  
  113.     if (mutex) {
  114.         switch_mutex_unlock(mutex);
  115.     }
  116.  
  117.     return ret;
  118. }
  119.  
  120. static switch_status_t cc_execute_sql(char *sql, switch_mutex_t *mutex)
  121. {
  122.     switch_cache_db_handle_t *dbh = NULL;
  123.     switch_status_t status = SWITCH_STATUS_FALSE;
  124.  
  125.     if (mutex) {
  126.         switch_mutex_lock(mutex);
  127.     }
  128.     if (!(dbh = ccpaas_get_db_handle())) {
  129.         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
  130.         goto end;
  131.     }
  132.  
  133.     status = switch_cache_db_execute_sql(dbh, sql, NULL);
  134.  
  135. end:
  136.  
  137.     switch_cache_db_release_db_handle(&dbh);
  138.  
  139.     if (mutex) {
  140.         switch_mutex_unlock(mutex);
  141.     }
  142.  
  143.     return status;
  144. }
  145.  
  146. //更新失败的呼叫
  147. static int cc_task_update_fail(char *task_id, char *run_id){
  148. char *sql;
  149. char *sql_del;
  150. sql = switch_mprintf("update uncall_task.ccpaas_run_%s set call_status = '3' where id = '%s'",task_id,run_id);
  151. sql_del = switch_mprintf("delete from `uncall_task`.`phone_memory` where task_table='%s' and task_tabke_id='%s' ;",task_id,run_id);
  152. cc_execute_sql(sql, globals.sql_mutex);
  153. switch_safe_free(sql);
  154. cc_execute_sql(sql_del, globals.sql_mutex);
  155. switch_safe_free(sql_del);
  156. return 1;
  157. }
  158.  
  159. #define ORIGINATE_SYNTAX "<call url> <exten>|&<application_name>(<app_args>) [<dialplan>] [<context>] [<cid_name>] [<cid_num>] [<timeout_sec>]"
  160. static int cc_outbound_task(char *aleg, char *exten , char *dp, char *context, char *cid_name , char *cid_num , char *number , char *task_id, char *run_id){
  161.     
  162. switch_channel_t *caller_channel;
  163.     switch_core_session_t *caller_session = NULL;
  164.     
  165.     uint32_t timeout = 30;
  166.     switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
  167.     switch_status_t status = SWITCH_STATUS_SUCCESS;
  168.     if (switch_ivr_originate_ccpaas(NULL, &caller_session, &cause, aleg, timeout, NULL, cid_name, cid_num, NULL, NULL, SOF_NONE, NULL, task_id , run_id) != SWITCH_STATUS_SUCCESS
  169.         || !caller_session) {
  170. //-ERR call fail
  171. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " --> ccpaas ---------->+Fail %s_ %s \n",task_id,run_id);
  172.         cc_task_update_fail(task_id,run_id);
  173. goto done;
  174.     }
  175.     caller_channel = switch_core_session_get_channel(caller_session);
  176.     switch_ivr_session_transfer(caller_session, exten, dp, context);
  177.     switch_core_session_rwunlock(caller_session);
  178. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,"ccpaas---------->+OK %s\n", switch_core_session_get_uuid(caller_session));
  179.  
  180. done:
  181.     return status;
  182. }
  183.  
  184. static void *SWITCH_THREAD_FUNC ccpass_thread(switch_thread_t *thread, void *obj)
  185. {
  186.     struct cc_paas_call_obj *call_obj = (struct cc_paas_call_obj *) obj;
  187.     switch_memory_pool_t *pool = call_obj->pool;
  188. char aleg[128]={'\0'};
  189. char uid[32]={'\0'};
  190. char *exten=call_obj->exten;
  191. char *dp="XML";
  192. char *context = call_obj->context;
  193. char *cid_name=call_obj->cid_name;
  194. char *cid_num= call_obj->cid_num;
  195. char *number = call_obj->number;
  196. char *gateway = call_obj->gateway;
  197. char *task_id = call_obj->task_table;
  198. char *run_id = call_obj->task_tabke_id;
  199. snprintf(aleg,sizeof(aleg),"{ignore_early_media=true,ccpaas_id=%s_%s}sofia/gateway/%s/%s",task_id,run_id,gateway,call_obj->number);
  200. snprintf(uid,sizeof(uid),"%s",call_obj->uid);
  201. cc_outbound_task(aleg,exten,dp,context,cid_name,cid_num,number,task_id,run_id);
  202. call_obj = NULL;
  203.     switch_core_destroy_memory_pool(&pool);
  204. pool = NULL;
  205.     return NULL;
  206. }
  207.  
  208. static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames)
  209. {
  210.     //callback_t *cbt = (callback_t *) pArg; 
  211.     //switch_copy_string(cbt->buf, argv[0], cbt->len);  
  212.     switch_thread_t *thread;
  213.     switch_threadattr_t *thd_attr;
  214.     switch_memory_pool_t *pool = NULL;
  215.     struct cc_paas_call_obj *call_obj;
  216. char *sql_mark;
  217. char number[32]={'\0'};
  218. char uid[32]={'\0'};
  219. char gateway[32]={'\0'};
  220. char exten[32]={'\0'};
  221. char context[32]={'\0'};
  222. char cid_name[32]={'\0'};
  223. char cid_num[32]={'\0'};
  224. char task_table[32]={'\0'};
  225. char task_tabke_id[32]={'\0'};
  226. snprintf(number,sizeof(number),"%s",argv[0]);
  227. snprintf(gateway,sizeof(gateway),"%s",argv[1]);
  228. snprintf(exten,sizeof(exten),"%s",argv[2]);
  229. snprintf(context,sizeof(context),"%s",argv[3]);
  230. snprintf(cid_name,sizeof(cid_name),"%s",argv[4]);
  231. snprintf(cid_num,sizeof(cid_num),"%s",argv[5]);
  232. snprintf(task_table,sizeof(task_table),"%s",argv[6]);
  233. snprintf(task_tabke_id,sizeof(task_tabke_id),"%s",argv[7]);
  234.  
  235.     switch_core_new_memory_pool(&pool);
  236.     switch_threadattr_create(&thd_attr, pool);
  237.     switch_threadattr_detach_set(thd_attr, 1);
  238.     /* TBD figure out how much space we need by looking at the xml_t when stacksize == 0 */
  239.     switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
  240.     call_obj = switch_core_alloc(pool, sizeof(*call_obj));
  241. switch_copy_string(call_obj->number, number, sizeof(call_obj->number));
  242. switch_copy_string(call_obj->uid, uid, sizeof(call_obj->uid));
  243. switch_copy_string(call_obj->gateway,gateway,sizeof(gateway));
  244. switch_copy_string(call_obj->exten,exten,sizeof(exten));
  245. switch_copy_string(call_obj->context,context,sizeof(context));
  246. switch_copy_string(call_obj->cid_name,gateway,sizeof(cid_name));
  247. switch_copy_string(call_obj->cid_num,cid_num,sizeof(cid_num));
  248. switch_copy_string(call_obj->task_table,task_table,sizeof(task_table));
  249. switch_copy_string(call_obj->task_tabke_id,task_tabke_id,sizeof(task_tabke_id));
  250. call_obj->pool = pool;
  251. sql_mark = switch_mprintf("update `uncall_task`.`phone_memory` set send ='1' where task_table = '%s' and task_tabke_id = '%s';",task_table,task_tabke_id);
  252.     
  253. cc_execute_sql(sql_mark, globals.sql_mutex);
  254.     switch_safe_free(sql_mark);
  255.     switch_thread_create(&thread, thd_attr, ccpass_thread, call_obj, pool);
  256. switch_yield(1000);
  257.     return 0;
  258. }
  259.  
  260. static switch_status_t read_config_file(switch_xml_t *xml, switch_xml_t *cfg) {
  261.     
  262. const char *cf = "fifo.conf";
  263.     switch_xml_t settings;
  264.  
  265.     if (!(*xml = switch_xml_open_cfg(cf, cfg, NULL))) {
  266.         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
  267.         return SWITCH_STATUS_TERM;
  268.     }
  269.     if ((settings = switch_xml_child(*cfg, "settings"))) {
  270.         switch_xml_t param;
  271.         for (param = switch_xml_child(settings, "param"); param; param = param->next) {
  272.             char *var = (char*)switch_xml_attr_soft(param, "name");
  273.             char *val = (char*)switch_xml_attr_soft(param, "value");
  274.             if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) {
  275.                 if (switch_odbc_available() || switch_pgsql_available()) {
  276.                     switch_set_string(globals.odbc_dsn, val);
  277.                 } else {
  278.                     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
  279.                 }
  280. }
  281.         }
  282.     }
  283.     return SWITCH_STATUS_SUCCESS;
  284. }
  285.  
  286. /*
  287.  * 获取外呼任务数
  288.  */
  289. static void ccpaas_outbound_sql()
  290. {
  291. char outbound_count[80] = "";
  292. char *sql;
  293. callback_t cbt = { 0 };
  294. cbt.buf = outbound_count;
  295. cbt.len = sizeof(outbound_count);
  296. sql = switch_mprintf("select phone, gateway, exten, context, cid_name, cid_num, task_table, task_tabke_id, company_code from `uncall_task`.`phone_memory` where send='0'");
  297. ccpaas_execute_sql_callback(globals.sql_mutex, sql, sql2str_callback, &cbt);
  298. switch_safe_free(sql);
  299. //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,"ccpass---------->+OK \n");
  300. }
  301.  
  302. SWITCH_STANDARD_API(ccpass_api_function){
  303. stream->write_function(stream , "CCPAAS , V 1.0 \n");
  304. return SWITCH_STATUS_SUCCESS;
  305. }
  306.  
  307.  
  308. SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_ccpaas_shutdown){
  309. return SWITCH_STATUS_SUCCESS;
  310. }
  311. SWITCH_MODULE_LOAD_FUNCTION(mod_ccpaas_load){
  312. switch_xml_t xml, cfg;
  313. switch_status_t status = SWITCH_STATUS_SUCCESS;
  314. switch_cache_db_handle_t *dbh = NULL;
  315. switch_api_interface_t *api_interface;
  316. strncpy(globals.hostname, switch_core_get_switchname(), sizeof(globals.hostname) - 1);
  317.  
  318. if ((status = read_config_file(&xml, &cfg)) != SWITCH_STATUS_SUCCESS) return status;
  319.  
  320. if (!(dbh = ccpaas_get_db_handle())) {
  321. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
  322. }
  323. /* connect my internal structure to the blank pointer passed to me */  
  324. *module_interface = switch_loadable_module_create_module_interface(pool, modname);
  325. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "CC-PAAS \n");
  326. //parse_config(SWITCH_FALSE);  
  327. SWITCH_ADD_API(api_interface , "ccpass" , "ccpass of status", ccpass_api_function, "[name]");
  328. /* indicate that the module should continue to be loaded */  
  329. return SWITCH_STATUS_SUCCESS;
  330. }
  331.  
  332.  
  333. SWITCH_MODULE_RUNTIME_FUNCTION(mod_ccpaas_runtime){
  334. while(1) {
  335. ccpaas_outbound_sql();
  336. switch_yield(100000);
  337. }
  338. }
  339. #define switch_set_string(_dst, _src) switch_copy_string(_dst, _src, sizeof(_dst))
  340. #define switch_cache_db_get_db_handle_dsn(_a, _b) _switch_cache_db_get_db_handle_dsn(_a, _b, __FILE__, __SWITCH_FUNC__, __LINE__)