/* requires immediate copying of string from return to retain data since otherwise it will immediately lose scope */ static char *filename_parse(char *filename, char *buffer, size_t len) { char *slash; if (ast_strlen_zero(filename)) { ast_log(LOG_WARNING, "No file name was provided for a file save option.\n"); } else if (filename[0] != '/') { char *build; build = alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(filename) + 3); sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, filename); filename = build; } ast_copy_string(buffer, filename, len); if ((slash = strrchr(filename, '/'))) { *slash = '\0'; } ast_mkdir(filename, 0777); return buffer; }
/*! * \brief Change monitored filename of channel * \param chan * \param fname_base new filename * \param need_lock * \retval 0 on success. * \retval -1 on failure. */ int AST_OPTIONAL_API_NAME(ast_monitor_change_fname)(struct ast_channel *chan, const char *fname_base, int need_lock) { if (ast_strlen_zero(fname_base)) { ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", ast_channel_name(chan)); return -1; } LOCK_IF_NEEDED(chan, need_lock); if (ast_channel_monitor(chan)) { int directory = strchr(fname_base, '/') ? 1 : 0; const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; const char *absolute_suffix = *fname_base == '/' ? "" : "/"; char tmpstring[sizeof(ast_channel_monitor(chan)->filename_base)] = ""; int i, fd[2] = { -1, -1 }, doexit = 0; /* before continuing, see if we're trying to rename the file to itself... */ snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base); /* try creating the directory just in case it doesn't exist */ if (directory) { char *name = ast_strdupa(tmpstring); ast_mkdir(dirname(name), 0777); } /*! * \note We cannot just compare filenames, due to symlinks, relative * paths, and other possible filesystem issues. We could use * realpath(3), but its use is discouraged. However, if we try to * create the same file from two different paths, the second will * fail, and so we have our notification that the filenames point to * the same path. * * Remember, also, that we're using the basename of the file (i.e. * the file without the format suffix), so it does not already exist * and we aren't interfering with the recording itself. */ ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, ast_channel_monitor(chan)->filename_base); if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 || (fd[1] = open(ast_channel_monitor(chan)->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { if (fd[0] < 0) { ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno)); } else { ast_debug(2, "No need to rename monitor filename to itself\n"); } doexit = 1; } /* Cleanup temporary files */ for (i = 0; i < 2; i++) { if (fd[i] >= 0) { while (close(fd[i]) < 0 && errno == EINTR); } } unlink(tmpstring); /* if previous monitor file existed in a subdirectory, the directory will not be removed */ unlink(ast_channel_monitor(chan)->filename_base); if (doexit) { UNLOCK_IF_NEEDED(chan, need_lock); return 0; } ast_copy_string(ast_channel_monitor(chan)->filename_base, tmpstring, sizeof(ast_channel_monitor(chan)->filename_base)); ast_channel_monitor(chan)->filename_changed = 1; } else { ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", ast_channel_name(chan), fname_base); } UNLOCK_IF_NEEDED(chan, need_lock); return 0; }
/*! \brief Start monitoring a channel * \param chan ast_channel struct to record * \param format_spec file format to use for recording * \param fname_base filename base to record to * \param need_lock whether to lock the channel mutex * \param stream_action whether to record the input and/or output streams. X_REC_IN | X_REC_OUT is most often used * Creates the file to record, if no format is specified it assumes WAV * It also sets channel variable __MONITORED=yes * \retval 0 on success * \retval -1 on failure */ int AST_OPTIONAL_API_NAME(ast_monitor_start)(struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action) { int res = 0; LOCK_IF_NEEDED(chan, need_lock); if (!(ast_channel_monitor(chan))) { struct ast_channel_monitor *monitor; char *channel_name, *p; /* Create monitoring directory if needed */ ast_mkdir(ast_config_AST_MONITOR_DIR, 0777); if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { UNLOCK_IF_NEEDED(chan, need_lock); return -1; } /* Determine file names */ if (!ast_strlen_zero(fname_base)) { int directory = strchr(fname_base, '/') ? 1 : 0; const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; const char *absolute_suffix = *fname_base == '/' ? "" : "/"; snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in", absolute, absolute_suffix, fname_base); snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out", absolute, absolute_suffix, fname_base); snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s", absolute, absolute_suffix, fname_base); /* try creating the directory just in case it doesn't exist */ if (directory) { char *name = ast_strdupa(monitor->filename_base); ast_mkdir(dirname(name), 0777); } } else { ast_mutex_lock(&monitorlock); snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%lu", ast_config_AST_MONITOR_DIR, seq); snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%lu", ast_config_AST_MONITOR_DIR, seq); seq++; ast_mutex_unlock(&monitorlock); /* Replace all '/' chars from the channel name with '-' chars. */ channel_name = ast_strdupa(ast_channel_name(chan)); for (p = channel_name; (p = strchr(p, '/')); ) { *p = '-'; } snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); monitor->filename_changed = 1; } monitor->stop = ast_monitor_stop; /* Determine file format */ if (!ast_strlen_zero(format_spec)) { monitor->format = ast_strdup(format_spec); } else { monitor->format = ast_strdup("wav"); } /* open files */ if (stream_action & X_REC_IN) { if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) ast_filedelete(monitor->read_filename, NULL); if (!(monitor->read_stream = ast_writefile(monitor->read_filename, monitor->format, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { ast_log(LOG_WARNING, "Could not create file %s\n", monitor->read_filename); ast_free(monitor); UNLOCK_IF_NEEDED(chan, need_lock); return -1; } } else monitor->read_stream = NULL; if (stream_action & X_REC_OUT) { if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { ast_filedelete(monitor->write_filename, NULL); } if (!(monitor->write_stream = ast_writefile(monitor->write_filename, monitor->format, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { ast_log(LOG_WARNING, "Could not create file %s\n", monitor->write_filename); if (monitor->read_stream) { ast_closestream(monitor->read_stream); } ast_free(monitor); UNLOCK_IF_NEEDED(chan, need_lock); return -1; } } else monitor->write_stream = NULL; ast_channel_monitor_set(chan, monitor); ast_monitor_set_state(chan, AST_MONITOR_RUNNING); /* so we know this call has been monitored in case we need to bill for it or something */ pbx_builtin_setvar_helper(chan, "__MONITORED","true"); ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStart", "Channel: %s\r\n" "Uniqueid: %s\r\n", ast_channel_name(chan), ast_channel_uniqueid(chan)); } else { ast_debug(1,"Cannot start monitoring %s, already monitored\n", ast_channel_name(chan)); res = -1; } UNLOCK_IF_NEEDED(chan, need_lock); return res; }
static int testserver_exec(struct ast_channel *chan, const char *data) { int res = 0; char testid[80]=""; char fn[80]; FILE *f; if (ast_channel_state(chan) != AST_STATE_UP) res = ast_answer(chan); /* Read version */ ast_debug(1, "Read client version\n"); if (!res) res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0); if (res > 0) res = 0; ast_debug(1, "client version: %s\n", testid); ast_debug(1, "Transmit server version\n"); res = ast_safe_sleep(chan, 1000); if (!res) res = ast_dtmf_stream(chan, NULL, "8378*1#", 0, 0); if (res > 0) res = 0; if (!res) res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0); ast_debug(1, "read test identifier: %s\n", testid); /* Check for sneakyness */ if (strchr(testid, '/')) res = -1; if ((res >=0) && (!ast_strlen_zero(testid))) { /* Got a Test ID! Whoo hoo! */ /* Make the directory to hold the test results in case it's not there */ snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR); ast_mkdir(fn, 0777); snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid); if ((f = fopen(fn, "w+"))) { setlinebuf(f); fprintf(f, "SERVERCHAN: %s\n", ast_channel_name(chan)); fprintf(f, "SERVERTEST ID: %s\n", testid); fprintf(f, "ANSWER: PASS\n"); ast_debug(1, "Processing Test ID '%s'\n", testid); res = ast_safe_sleep(chan, 1000); if (!res) { /* Step 1: Send "1" */ ast_debug(1, "TestServer: 1. Send DTMF 1\n"); res = ast_dtmf_stream(chan, NULL, "1", 0,0 ); fprintf(f, "SEND DTMF 1: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res = 0; } if (!res) { /* Step 2: Wait for "2" */ ast_debug(1, "TestServer: 2. Wait DTMF 2\n"); res = ast_waitfordigit(chan, 3000); fprintf(f, "WAIT DTMF 2: %s\n", (res != '2') ? "FAIL" : "PASS"); if (res == '2') res = 0; else res = -1; } if (!res) { /* Step 3: Measure noise */ ast_debug(1, "TestServer: 3. Measure noise\n"); res = measurenoise(chan, 6000, "TestServer"); fprintf(f, "MEASURENOISE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res); if (res > 0) res = 0; } if (!res) { /* Step 4: Send "4" */ ast_debug(1, "TestServer: 4. Send DTMF 4\n"); res = ast_dtmf_stream(chan, NULL, "4", 0, 0); fprintf(f, "SEND DTMF 4: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res = 0; } if (!res) { /* Step 5: Wait one second */ ast_debug(1, "TestServer: 5. Wait one second\n"); res = ast_safe_sleep(chan, 1000); fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res = 0; } if (!res) { /* Step 6: Measure noise */ ast_debug(1, "TestServer: 6. Measure tone\n"); res = measurenoise(chan, 4000, "TestServer"); fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res); if (res > 0) res = 0; } if (!res) { /* Step 7: Send "5" */ ast_debug(1, "TestServer: 7. Send DTMF 5\n"); res = ast_dtmf_stream(chan, NULL, "5", 0, 0); fprintf(f, "SEND DTMF 5: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res = 0; } if (!res) { /* Step 8: Transmit tone noise */ ast_debug(1, "TestServer: 8. Transmit tone\n"); res = sendnoise(chan, 6000); fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS"); } if (!res || (res == '7')) { /* Step 9: Wait for "7" */ ast_debug(1, "TestServer: 9. Wait DTMF 7\n"); if (!res) res = ast_waitfordigit(chan, 3000); fprintf(f, "WAIT DTMF 7: %s\n", (res != '7') ? "FAIL" : "PASS"); if (res == '7') res = 0; else res = -1; } if (!res) { res = ast_safe_sleep(chan, 1000); } if (!res) { /* Step 10: Send "8" */ ast_debug(1, "TestServer: 10. Send DTMF 8\n"); res = ast_dtmf_stream(chan, NULL, "8", 0, 0); fprintf(f, "SEND DTMF 8: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res = 0; } if (!res) { /* Step 11: Wait for hangup to arrive! */ ast_debug(1, "TestServer: 11. Waiting for hangup\n"); res = ast_safe_sleep(chan, 10000); fprintf(f, "WAIT HANGUP: %s\n", (res < 0) ? "PASS" : "FAIL"); } ast_log(LOG_NOTICE, "-- TEST COMPLETE--\n"); fprintf(f, "-- END TEST--\n"); fclose(f); res = -1; } else res = -1; } else { ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", ast_channel_name(chan)); res = -1; } return res; }
static int testclient_exec(struct ast_channel *chan, const char *data) { int res = 0; const char *testid=data; char fn[80]; char serverver[80]; FILE *f; /* Check for test id */ if (ast_strlen_zero(testid)) { ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n"); return -1; } if (ast_channel_state(chan) != AST_STATE_UP) res = ast_answer(chan); /* Wait a few just to be sure things get started */ res = ast_safe_sleep(chan, 3000); /* Transmit client version */ if (!res) res = ast_dtmf_stream(chan, NULL, "8378*1#", 0, 0); ast_debug(1, "Transmit client version\n"); /* Read server version */ ast_debug(1, "Read server version\n"); if (!res) res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0); if (res > 0) res = 0; ast_debug(1, "server version: %s\n", serverver); if (res > 0) res = 0; if (!res) res = ast_safe_sleep(chan, 1000); /* Send test id */ if (!res) res = ast_dtmf_stream(chan, NULL, testid, 0, 0); if (!res) res = ast_dtmf_stream(chan, NULL, "#", 0, 0); ast_debug(1, "send test identifier: %s\n", testid); if ((res >=0) && (!ast_strlen_zero(testid))) { /* Make the directory to hold the test results in case it's not there */ snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR); ast_mkdir(fn, 0777); snprintf(fn, sizeof(fn), "%s/testresults/%s-client.txt", ast_config_AST_LOG_DIR, testid); if ((f = fopen(fn, "w+"))) { setlinebuf(f); fprintf(f, "CLIENTCHAN: %s\n", ast_channel_name(chan)); fprintf(f, "CLIENTTEST ID: %s\n", testid); fprintf(f, "ANSWER: PASS\n"); res = 0; if (!res) { /* Step 1: Wait for "1" */ ast_debug(1, "TestClient: 2. Wait DTMF 1\n"); res = ast_waitfordigit(chan, 3000); fprintf(f, "WAIT DTMF 1: %s\n", (res != '1') ? "FAIL" : "PASS"); if (res == '1') res = 0; else res = -1; } if (!res) { res = ast_safe_sleep(chan, 1000); } if (!res) { /* Step 2: Send "2" */ ast_debug(1, "TestClient: 2. Send DTMF 2\n"); res = ast_dtmf_stream(chan, NULL, "2", 0, 0); fprintf(f, "SEND DTMF 2: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res = 0; } if (!res) { /* Step 3: Wait one second */ ast_debug(1, "TestClient: 3. Wait one second\n"); res = ast_safe_sleep(chan, 1000); fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res = 0; } if (!res) { /* Step 4: Measure noise */ ast_debug(1, "TestClient: 4. Measure noise\n"); res = measurenoise(chan, 5000, "TestClient"); fprintf(f, "MEASURENOISE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res); if (res > 0) res = 0; } if (!res) { /* Step 5: Wait for "4" */ ast_debug(1, "TestClient: 5. Wait DTMF 4\n"); res = ast_waitfordigit(chan, 3000); fprintf(f, "WAIT DTMF 4: %s\n", (res != '4') ? "FAIL" : "PASS"); if (res == '4') res = 0; else res = -1; } if (!res) { /* Step 6: Transmit tone noise */ ast_debug(1, "TestClient: 6. Transmit tone\n"); res = sendnoise(chan, 6000); fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS"); } if (!res || (res == '5')) { /* Step 7: Wait for "5" */ ast_debug(1, "TestClient: 7. Wait DTMF 5\n"); if (!res) res = ast_waitfordigit(chan, 3000); fprintf(f, "WAIT DTMF 5: %s\n", (res != '5') ? "FAIL" : "PASS"); if (res == '5') res = 0; else res = -1; } if (!res) { /* Step 8: Wait one second */ ast_debug(1, "TestClient: 8. Wait one second\n"); res = ast_safe_sleep(chan, 1000); fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res = 0; } if (!res) { /* Step 9: Measure noise */ ast_debug(1, "TestClient: 9. Measure tone\n"); res = measurenoise(chan, 4000, "TestClient"); fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res); if (res > 0) res = 0; } if (!res) { /* Step 10: Send "7" */ ast_debug(1, "TestClient: 10. Send DTMF 7\n"); res = ast_dtmf_stream(chan, NULL, "7", 0, 0); fprintf(f, "SEND DTMF 7: %s\n", (res < 0) ? "FAIL" : "PASS"); if (res > 0) res =0; } if (!res) { /* Step 11: Wait for "8" */ ast_debug(1, "TestClient: 11. Wait DTMF 8\n"); res = ast_waitfordigit(chan, 3000); fprintf(f, "WAIT DTMF 8: %s\n", (res != '8') ? "FAIL" : "PASS"); if (res == '8') res = 0; else res = -1; } if (!res) { res = ast_safe_sleep(chan, 1000); } if (!res) { /* Step 12: Hangup! */ ast_debug(1, "TestClient: 12. Hangup\n"); } ast_debug(1, "-- TEST COMPLETE--\n"); fprintf(f, "-- END TEST--\n"); fclose(f); res = -1; } else res = -1; } else { ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", ast_channel_name(chan)); res = -1; } return res; }
static int load_module(void) { struct ast_config *cfg; struct ast_flags config_flags = { 0 }; const char *tmp; if ((cfg = ast_config_load(cel_config, config_flags))) { ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "usegmtime")), RADIUS_FLAG_USEGMTIME); if ((tmp = ast_variable_retrieve(cfg, "radius", "radiuscfg"))) { ast_copy_string(radiuscfg, tmp, sizeof(radiuscfg)); } ast_config_destroy(cfg); } else { return AST_MODULE_LOAD_DECLINE; } /* create dir /var/lib/cdr if it does not exist. add by liucl */ if (access(cdr_directory,F_OK) == -1){ ast_log(LOG_DEBUG,"cdr_directory %s is not exist, I will create it.\n",cdr_directory); if(ast_mkdir(cdr_directory, 0755) == -1) { ast_log(LOG_ERROR,"Failed to create %s\n", cdr_directory); }else{ ast_log(LOG_DEBUG,"Create directory %s is OK\n",cdr_directory); } } /* liucl add end*/ /* * start logging * * NOTE: Yes this causes a slight memory leak if the module is * unloaded. However, it is better than a crash if cdr_radius * and cel_radius are both loaded. */ tmp = ast_strdup("asterisk"); if (tmp) { rc_openlog((char *) tmp); } /* read radiusclient-ng config file */ if (!(rh = rc_read_config(radiuscfg))) { ast_log(LOG_NOTICE, "Cannot load radiusclient-ng configuration file %s.\n", radiuscfg); return AST_MODULE_LOAD_DECLINE; } /* read radiusclient-ng dictionaries */ if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary"))) { ast_log(LOG_NOTICE, "Cannot load radiusclient-ng dictionary file.\n"); rc_destroy(rh); rh = NULL; return AST_MODULE_LOAD_DECLINE; } if (ast_cel_backend_register(RADIUS_BACKEND_NAME, radius_log)) { rc_destroy(rh); rh = NULL; return AST_MODULE_LOAD_DECLINE; } else { /* * * Create a independent thread to monitoring /var/lib/cdr. * * If there is file in the directory, then send it to radius. * * add by liucl * */ start_monitor(); return AST_MODULE_LOAD_SUCCESS; } }