Browse Source

Create metadata file and move it to spool directory when call finishes.

We create a metadata file for each call. The metadata files will all end up
in a spool directory for the rtpengine.

Each in-progress file has the format: "rtpengine-meta-$RANDHEX.tmp" and
goes in /tmp/. When a call finishes, it is moved to the spool directory
in sub-directory /var/spool/rtpengine/metadata/ and we change the file
extension to ".txt".

The metadata file contains references to all PCAP recording files associated
with a call, and it includes generic metadata at the tail of the file.
One absolute path for a PCAP file per line, followed by two blank lines,
followed by the metadata passed in to the rtpengine through an external
command.

RTP Engine checks for the spool directory "/var/spool/rtpengine" on startup.
If it's not there, it fails. If it's there, it sets up "metadata" and
"recordings" inner directories. This is where RTP Engine will write call
metadata files and PCAP files.
pull/245/head
Dylan Mikus 10 years ago
committed by Eric Green
parent
commit
692b12944c
3 changed files with 128 additions and 6 deletions
  1. +68
    -6
      daemon/call.c
  2. +3
    -0
      daemon/call.h
  3. +57
    -0
      daemon/main.c

+ 68
- 6
daemon/call.c View File

@ -133,7 +133,7 @@ static void __monologue_destroy(struct call_monologue *monologue);
static int monologue_destroy(struct call_monologue *ml);
/* Generate a random PCAP filepath to write recorded RTP stream. */
void setup_recording_files(struct call *call, struct call_monologue *monologue);
str *setup_recording_file(struct call *call, struct call_monologue *monologue);
/* Generates a random string sandwiched between affixes. */
char *rand_affixed_str(int num_bytes, char *prefix, char *suffix);
/* Generates a hex string representing n random bytes. len(rand_str) = 2*num_bytes + 1 */
@ -1532,7 +1532,10 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams,
ml_media = other_ml_media = NULL;
setup_recording_files(call, monologue);
str *pcap_path = setup_recording_file(call, monologue);
if (pcap_path != NULL) {
fprintf(call->meta_fp, "%s\n", pcap_path->s);
}
for (media_iter = streams->head; media_iter; media_iter = media_iter->next) {
sp = media_iter->data;
@ -2225,12 +2228,51 @@ void call_destroy(struct call *c) {
c->recording_pcaps = g_slist_delete_link(c->recording_pcaps, c->recording_pcaps);
}
// TODO - here is where we write out metadata for IPC communication
meta_file_finish(c);
free(c->metadata);
rwlock_unlock_w(&c->master_lock);
}
/**
* Writes metadata to metafile, closes file, and renames it to finished location.
* Returns non-zero for failure.
*/
int meta_file_finish(struct call *call) {
int return_code = 0;
if (call->meta_fp != NULL) {
fprintf(call->meta_fp, "\n%s\n", call->metadata->s);
fclose(call->meta_fp);
// Get the filename (in between its directory and the file extension)
// and move it to the finished file location.
// Rename extension to ".txt".
int fn_len;
char *meta_filename = strrchr(call->meta_filepath->s, '/');
char *meta_ext = NULL;
if (meta_filename == NULL)
meta_filename = call->meta_filepath->s;
else
meta_filename = meta_filename + 1;
// We can always expect a file extension
meta_ext = strrchr(meta_filename, '.');
fn_len = meta_ext - meta_filename;
int prefix_len = 30; // for "/var/spool/rtpengine/metadata/"
int ext_len = 4; // for ".txt"
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, ext_len+1, ".txt");
return_code = return_code | rename(call->meta_filepath->s, new_metapath);
}
if (call->meta_filepath != NULL) {
free(call->meta_filepath->s);
free(call->meta_filepath);
}
return return_code;
}
/* XXX move these */
@ -2334,6 +2376,22 @@ static struct call *call_create(const str *callid, struct callmaster *m) {
c->created = poller_now;
c->dtls_cert = dtls_cert();
c->tos = m->conf.default_tos;
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);
c->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(c->meta_filepath->s);
free(c->meta_filepath);
c->meta_filepath = NULL;
}
c->meta_fp = mfp;
return c;
}
@ -2867,12 +2925,13 @@ out:
/**
* Generate a random PCAP filepath to write recorded RTP stream.
*/
void setup_recording_files(struct call *call, struct call_monologue *monologue) {
str *setup_recording_file(struct call *call, struct call_monologue *monologue) {
str *recording_path = NULL;
if (call->record_call
&& monologue->recording_pd == NULL && monologue->recording_pdumper == NULL) {
int rand_bytes = 16;
str *recording_path = malloc(sizeof(str));
char *path_chars = rand_affixed_str(rand_bytes, "/tmp/", ".pcap");
recording_path = malloc(sizeof(str));
char *path_chars = rand_affixed_str(rand_bytes, "/var/spool/rtpengine/recordings/", ".pcap");
recording_path = str_init(recording_path, path_chars);
monologue->recording_path = recording_path;
@ -2882,9 +2941,12 @@ void setup_recording_files(struct call *call, struct call_monologue *monologue)
monologue->recording_pd = pcap_open_dead(DLT_RAW, 65535);
monologue->recording_pdumper = pcap_dump_open(monologue->recording_pd, recording_path);
} else {
monologue->recording_path = NULL;
monologue->recording_pd = NULL;
monologue->recording_pdumper = NULL;
}
return recording_path;
}
/**


+ 3
- 0
daemon/call.h View File

@ -437,6 +437,9 @@ struct call {
unsigned int redis_hosted_db;
unsigned int foreign_call; // created_via_redis_notify call
str *meta_filepath;
FILE *meta_fp;
str *metadata;
};


+ 57
- 0
daemon/main.c View File

@ -11,6 +11,8 @@
#include <stdlib.h>
#include <time.h>
#include <openssl/ssl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "poller.h"
#include "control_tcp.h"
@ -549,6 +551,13 @@ static void create_everything(struct main_context *ctx) {
struct timeval redis_start, redis_stop;
double redis_diff = 0;
// TODO this should be a configurable path
char spoolpath[] = "/var/spool/rtpengine";
if (!maybe_create_spool_dir(spoolpath)) {
fprintf(stderr, "Error while setting up spool directory \"%s\".\n", spoolpath);
exit(-1);
}
if (table < 0)
goto no_kernel;
if (kernel_create_table(table)) {
@ -686,6 +695,54 @@ no_kernel:
set_graphite_interval_tv(&tmp_tv);
}
/**
* Sets up the spool directory for RTP Engine.
* If the directory does not exist, return FALSE.
* If the directory exists, but "$dirpath/metadata" or "$dirpath/recordings"
* exist as non-directory files, return FALSE.
* Otherwise, return TRUE.
*
* Create the "metadata" and "recordings" directories if they are not there.
*/
int maybe_create_spool_dir(char *dirpath) {
struct stat info;
int spool_good = TRUE;
if (stat(dirpath, &info) != 0) {
fprintf(stderr, "Spool directory \"%s\" does not exist.\n", dirpath);
spool_good = FALSE;
} else if (!S_ISDIR(info.st_mode)) {
fprintf(stderr, "Spool file exists, but \"%s\" is not a directory.\n", dirpath);
spool_good = FALSE;
} else {
// Spool directory exists. Make sure it has inner directories.
int path_len = strlen(dirpath);
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);
if (stat(meta_path, &info) != 0) {
fprintf(stdout, "Creating metadata directory \"%s\".\n", meta_path);
mkdir(meta_path, 0700);
} else if(!S_ISDIR(info.st_mode)) {
fprintf(stderr, "Metadata file exists, but \"%s\" is not a directory.\n", meta_path);
spool_good = FALSE;
}
if (stat(rec_path, &info) != 0) {
fprintf(stdout, "Creating recordings directory \"%s\".\n", rec_path);
mkdir(rec_path, 0700);
} else if(!S_ISDIR(info.st_mode)) {
fprintf(stderr, "Recordings file exists, but \"%s\" is not a directory.\n", rec_path);
spool_good = FALSE;
}
}
return spool_good;
}
int main(int argc, char **argv) {
struct main_context ctx;
int idx=0;


Loading…
Cancel
Save