Browse Source

Added command line option for the spool directory for recordings.

Command line option is "--recording-dir".
Renamed inner recording spool "recordings" to "pcaps".
This is to avoid name sharing conflicts with the "--recording-dir" command
line option, which specifies the recordings spool directory, and the
"$RECORDING_DIR/recordings" inner directory. Changing the inner directory
name to "pcaps" removes this name collision.

In the process, I changed the function names in fs.h to be consistent with
other functions. The names are structure like "$OBJECT_$VERB".
pull/245/head
Dylan Mikus 10 years ago
committed by Eric Green
parent
commit
2c1685b807
5 changed files with 75 additions and 45 deletions
  1. +2
    -2
      daemon/call.c
  2. +1
    -1
      daemon/call_interfaces.c
  3. +66
    -38
      daemon/fs.c
  4. +3
    -3
      daemon/fs.h
  5. +3
    -1
      daemon/main.c

+ 2
- 2
daemon/call.c View File

@ -1526,7 +1526,7 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams,
ml_media = other_ml_media = NULL; ml_media = other_ml_media = NULL;
str *pcap_path = setup_recording_file(call, monologue);
str *pcap_path = recording_setup_file(call, monologue);
if (pcap_path != NULL && call->meta_fp != NULL) { if (pcap_path != NULL && call->meta_fp != NULL) {
fprintf(call->meta_fp, "%s\n", pcap_path->s); fprintf(call->meta_fp, "%s\n", pcap_path->s);
} }
@ -2222,7 +2222,7 @@ void call_destroy(struct call *c) {
c->recording_pcaps = g_slist_delete_link(c->recording_pcaps, c->recording_pcaps); c->recording_pcaps = g_slist_delete_link(c->recording_pcaps, c->recording_pcaps);
} }
meta_file_finish(c);
meta_finish_file(c);
free(c->metadata); free(c->metadata);
rwlock_unlock_w(&c->master_lock); rwlock_unlock_w(&c->master_lock);


+ 1
- 1
daemon/call_interfaces.c View File

@ -690,7 +690,7 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster
if (recordcall.s && !str_cmp(&recordcall, "yes")) { if (recordcall.s && !str_cmp(&recordcall, "yes")) {
if (!call->record_call) { if (!call->record_call) {
setup_meta_file(call);
meta_setup_file(call);
call->record_call = 1; call->record_call = 1;
} }
bencode_dictionary_get_str(input, "metadata", &metadata); bencode_dictionary_get_str(input, "metadata", &metadata);


+ 66
- 38
daemon/fs.c View File

@ -12,6 +12,8 @@
int maybe_create_spool_dir(char *dirpath); int maybe_create_spool_dir(char *dirpath);
// Global file reference to the spool directory.
static char *spooldir = NULL;
/** /**
@ -19,53 +21,70 @@ int maybe_create_spool_dir(char *dirpath);
* Check for or create the RTP Engine spool directory. * Check for or create the RTP Engine spool directory.
*/ */
void fs_init(char *spoolpath) { void fs_init(char *spoolpath) {
// TODO should we change the umask at all?
// Whether or not to fail if the spool directory does not exist.
int dne_fail;
if (spoolpath == NULL || spoolpath[0] == '\0') {
spoolpath = "/var/spool/rtpengine";
dne_fail = FALSE;
} else {
dne_fail = TRUE;
int path_len = strlen(spoolpath);
// Get rid of trailing "/" if it exists. Other code adds that in when needed.
if (spoolpath[path_len-1] == '/') {
spoolpath[path_len-1] = '\0';
}
}
if (!maybe_create_spool_dir(spoolpath)) { if (!maybe_create_spool_dir(spoolpath)) {
fprintf(stderr, "Error while setting up spool directory \"%s\".\n", spoolpath); fprintf(stderr, "Error while setting up spool directory \"%s\".\n", spoolpath);
exit(-1);
if (dne_fail) {
fprintf(stderr, "Please run `mkdir %s` and start rtpengine again.\n", spoolpath);
exit(-1);
}
} else {
spooldir = strdup(spoolpath);
} }
} }
/** /**
* Sets up the spool directory for RTP Engine. * Sets up the spool directory for RTP Engine.
* If the directory does not exist, return FALSE. * If the directory does not exist, return FALSE.
* If the directory exists, but "$dirpath/metadata" or "$dirpath/recordings"
* If the directory exists, but "$spoolpath/metadata" or "$spoolpath/pcaps"
* exist as non-directory files, return FALSE. * exist as non-directory files, return FALSE.
* Otherwise, return TRUE. * Otherwise, return TRUE.
* *
* Create the "metadata" and "recordings" directories if they are not there.
* Create the "metadata" and "pcaps" directories if they are not there.
*/ */
int maybe_create_spool_dir(char *dirpath) {
int maybe_create_spool_dir(char *spoolpath) {
struct stat info; struct stat info;
int spool_good = TRUE; int spool_good = TRUE;
if (stat(dirpath, &info) != 0) {
fprintf(stderr, "Spool directory \"%s\" does not exist.\n", dirpath);
if (stat(spoolpath, &info) != 0) {
fprintf(stderr, "Spool directory \"%s\" does not exist.\n", spoolpath);
spool_good = FALSE; spool_good = FALSE;
} else if (!S_ISDIR(info.st_mode)) { } else if (!S_ISDIR(info.st_mode)) {
fprintf(stderr, "Spool file exists, but \"%s\" is not a directory.\n", dirpath);
fprintf(stderr, "Spool file exists, but \"%s\" is not a directory.\n", spoolpath);
spool_good = FALSE; spool_good = FALSE;
} else { } else {
// Spool directory exists. Make sure it has inner directories. // Spool directory exists. Make sure it has inner directories.
int path_len = strlen(dirpath);
int path_len = strlen(spoolpath);
char meta_path[path_len + 10]; char meta_path[path_len + 10];
char rec_path[path_len + 12];
snprintf(meta_path, path_len + 10, "%s/metadata", dirpath);
snprintf(rec_path, path_len + 12, "%s/recordings", dirpath);
char rec_path[path_len + 7];
snprintf(meta_path, path_len + 10, "%s/metadata", spoolpath);
snprintf(rec_path, path_len + 7, "%s/pcaps", spoolpath);
if (stat(meta_path, &info) != 0) { if (stat(meta_path, &info) != 0) {
fprintf(stdout, "Creating metadata directory \"%s\".\n", meta_path); fprintf(stdout, "Creating metadata directory \"%s\".\n", meta_path);
mkdir(meta_path, 0660); mkdir(meta_path, 0660);
} else if(!S_ISDIR(info.st_mode)) { } else if(!S_ISDIR(info.st_mode)) {
fprintf(stderr, "Metadata file exists, but \"%s\" is not a directory.\n", meta_path);
fprintf(stderr, "metadata file exists, but \"%s\" is not a directory.\n", meta_path);
spool_good = FALSE; spool_good = FALSE;
} }
if (stat(rec_path, &info) != 0) { if (stat(rec_path, &info) != 0) {
fprintf(stdout, "Creating recordings directory \"%s\".\n", rec_path);
fprintf(stdout, "Creating pcaps directory \"%s\".\n", rec_path);
mkdir(rec_path, 0660); mkdir(rec_path, 0660);
} else if(!S_ISDIR(info.st_mode)) { } else if(!S_ISDIR(info.st_mode)) {
fprintf(stderr, "Recordings file exists, but \"%s\" is not a directory.\n", rec_path);
fprintf(stderr, "pcaps file exists, but \"%s\" is not a directory.\n", rec_path);
spool_good = FALSE; spool_good = FALSE;
} }
} }
@ -77,29 +96,35 @@ int maybe_create_spool_dir(char *dirpath) {
* Create a call metadata file in a temporary location. * Create a call metadata file in a temporary location.
* Attaches the filepath and the file pointer to the call struct. * Attaches the filepath and the file pointer to the call struct.
*/ */
str *setup_meta_file(struct call *call) {
int rand_bytes = 16;
str *meta_filepath = malloc(sizeof(str));
// Initially file extension is ".tmp". When call is over, it changes to ".txt".
char *path_chars = rand_affixed_str(rand_bytes, "/tmp/rtpengine-meta-", ".tmp");
meta_filepath = str_init(meta_filepath, path_chars);
call->meta_filepath = meta_filepath;
FILE *mfp = fopen(meta_filepath->s, "w");
if (mfp == NULL) {
ilog(LOG_ERROR, "Could not open metadata file: %s", meta_filepath->s);
free(call->meta_filepath->s);
free(call->meta_filepath);
call->meta_filepath = NULL;
str *meta_setup_file(struct call *call) {
if (spooldir == NULL) {
// No spool directory was created, so we cannot have metadata files.
return NULL;
}
else {
int rand_bytes = 16;
str *meta_filepath = malloc(sizeof(str));
// Initially file extension is ".tmp". When call is over, it changes to ".txt".
char *path_chars = rand_affixed_str(rand_bytes, "/tmp/rtpengine-meta-", ".tmp");
meta_filepath = str_init(meta_filepath, path_chars);
call->meta_filepath = meta_filepath;
FILE *mfp = fopen(meta_filepath->s, "w");
if (mfp == NULL) {
ilog(LOG_ERROR, "Could not open metadata file: %s", meta_filepath->s);
free(call->meta_filepath->s);
free(call->meta_filepath);
call->meta_filepath = NULL;
}
call->meta_fp = mfp;
return meta_filepath;
} }
call->meta_fp = mfp;
return meta_filepath;
} }
/** /**
* Writes metadata to metafile, closes file, and renames it to finished location. * Writes metadata to metafile, closes file, and renames it to finished location.
* Returns non-zero for failure. * Returns non-zero for failure.
*/ */
int meta_file_finish(struct call *call) {
int meta_finish_file(struct call *call) {
int return_code = 0; int return_code = 0;
@ -139,10 +164,10 @@ int meta_file_finish(struct call *call) {
// We can always expect a file extension // We can always expect a file extension
meta_ext = strrchr(meta_filename, '.'); meta_ext = strrchr(meta_filename, '.');
fn_len = meta_ext - meta_filename; fn_len = meta_ext - meta_filename;
int prefix_len = 30; // for "/var/spool/rtpengine/metadata/"
int prefix_len = strlen(spooldir) + 10; // constant for "/metadata/" suffix
int ext_len = 4; // for ".txt" int ext_len = 4; // for ".txt"
char new_metapath[prefix_len + fn_len + ext_len + 1]; char new_metapath[prefix_len + fn_len + ext_len + 1];
snprintf(new_metapath, prefix_len+fn_len+1, "/var/spool/rtpengine/metadata/%s", meta_filename);
snprintf(new_metapath, prefix_len+fn_len+1, "%s/metadata/%s", spooldir, meta_filename);
snprintf(new_metapath + prefix_len+fn_len, ext_len+1, ".txt"); snprintf(new_metapath + prefix_len+fn_len, ext_len+1, ".txt");
return_code = return_code | rename(call->meta_filepath->s, new_metapath); return_code = return_code | rename(call->meta_filepath->s, new_metapath);
} }
@ -157,19 +182,22 @@ int meta_file_finish(struct call *call) {
/** /**
* Generate a random PCAP filepath to write recorded RTP stream. * Generate a random PCAP filepath to write recorded RTP stream.
*/ */
str *setup_recording_file(struct call *call, struct call_monologue *monologue) {
str *recording_setup_file(struct call *call, struct call_monologue *monologue) {
str *recording_path = NULL; str *recording_path = NULL;
if (call->record_call
if (spooldir != NULL
&& call->record_call
&& monologue->recording_pd == NULL && monologue->recording_pdumper == NULL) { && monologue->recording_pd == NULL && monologue->recording_pdumper == NULL) {
int rand_bytes = 16; int rand_bytes = 16;
recording_path = malloc(sizeof(str));
char *path_chars = rand_affixed_str(rand_bytes, "/var/spool/rtpengine/recordings/", ".pcap");
int rec_path_len = strlen(spooldir) + 8; // spool directory path + "/pcaps/"
char rec_path[rec_path_len];
snprintf(rec_path, rec_path_len, "%s/pcaps/", spooldir);
char *path_chars = rand_affixed_str(rand_bytes, rec_path, ".pcap");
recording_path = malloc(sizeof(str));
recording_path = str_init(recording_path, path_chars); recording_path = str_init(recording_path, path_chars);
monologue->recording_path = recording_path; monologue->recording_path = recording_path;
call->recording_pcaps = g_slist_prepend(call->recording_pcaps, g_strdup(path_chars)); call->recording_pcaps = g_slist_prepend(call->recording_pcaps, g_strdup(path_chars));
/* monologue->recording_file */
monologue->recording_pd = pcap_open_dead(DLT_RAW, 65535); monologue->recording_pd = pcap_open_dead(DLT_RAW, 65535);
monologue->recording_pdumper = pcap_dump_open(monologue->recording_pd, path_chars); monologue->recording_pdumper = pcap_dump_open(monologue->recording_pd, path_chars);
} else { } else {


+ 3
- 3
daemon/fs.h View File

@ -30,19 +30,19 @@ void fs_init(char *spooldir);
* metadata * metadata
* *
*/ */
str *setup_meta_file(struct call *call);
str *meta_setup_file(struct call *call);
/** /**
* Writes metadata to metafile, closes file, and renames it to finished location. * Writes metadata to metafile, closes file, and renames it to finished location.
* Returns non-zero for failure. * Returns non-zero for failure.
*/ */
int meta_file_finish(struct call *call);
int meta_finish_file(struct call *call);
/** /**
* Generate a random PCAP filepath to write recorded RTP stream. * Generate a random PCAP filepath to write recorded RTP stream.
* Returns path to created file. * Returns path to created file.
*/ */
str *setup_recording_file(struct call *call, struct call_monologue *monologue);
str *recording_setup_file(struct call *call, struct call_monologue *monologue);
/** /**
* Write out a PCAP packet with payload string. * Write out a PCAP packet with payload string.


+ 3
- 1
daemon/main.c View File

@ -87,6 +87,7 @@ static enum xmlrpc_format xmlrpc_fmt = XF_SEMS;
static int num_threads; static int num_threads;
static int delete_delay = 30; static int delete_delay = 30;
static int graphite_interval = 0; static int graphite_interval = 0;
static char *spooldir;
static void sighandler(gpointer x) { static void sighandler(gpointer x) {
sigset_t ss; sigset_t ss;
@ -323,6 +324,7 @@ static void options(int *argc, char ***argv) {
{ "homer", 0, 0, G_OPTION_ARG_STRING, &homerp, "Address of Homer server for RTCP stats","IP46:PORT"}, { "homer", 0, 0, G_OPTION_ARG_STRING, &homerp, "Address of Homer server for RTCP stats","IP46:PORT"},
{ "homer-protocol",0,0,G_OPTION_ARG_STRING, &homerproto, "Transport protocol for Homer (default udp)", "udp|tcp" }, { "homer-protocol",0,0,G_OPTION_ARG_STRING, &homerproto, "Transport protocol for Homer (default udp)", "udp|tcp" },
{ "homer-id", 0, 0, G_OPTION_ARG_STRING, &homer_id, "'Capture ID' to use within the HEP protocol", "INT" }, { "homer-id", 0, 0, G_OPTION_ARG_STRING, &homer_id, "'Capture ID' to use within the HEP protocol", "INT" },
{ "recording-dir", 0, 0, G_OPTION_ARG_STRING, &spooldir, "Directory for storing pcap and metadata files", "FILE" },
{ NULL, } { NULL, }
}; };
@ -519,7 +521,7 @@ static void init_everything() {
socket_init(); socket_init();
log_init(); log_init();
fs_init("/var/spool/rtpengine");
fs_init(spooldir);
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);
srandom(ts.tv_sec ^ ts.tv_nsec); srandom(ts.tv_sec ^ ts.tv_nsec);
SSL_library_init(); SSL_library_init();


Loading…
Cancel
Save