janus_text2pcap *janus_text2pcap_create(const char *dir, const char *filename, int truncate, gboolean text) { janus_text2pcap *tp; char newname[1024]; char *fname; FILE *f; if(truncate < 0) return NULL; /* Copy given filename or generate a random one */ if (filename == NULL) { g_snprintf(newname, sizeof(newname), "janus-text2pcap-%"SCNu32".%s", janus_random_uint32(), text ? "txt" : "pcap"); } else { g_strlcpy(newname, filename, sizeof(newname)); } if(dir != NULL) { /* Create the directory, if needed */ if(janus_mkdir(dir, 0755) < 0) { JANUS_LOG(LOG_ERR, "mkdir error: %d\n", errno); return NULL; } fname = g_strdup_printf("%s/%s", dir, newname); } else { fname = g_strdup(newname); } /* Try opening the file now */ f = fopen(fname, "ab"); if (f == NULL) { JANUS_LOG(LOG_ERR, "fopen(%s) error: %d\n", fname, errno); g_free(fname); return NULL; } /* Create the text2pcap instance */ tp = g_malloc(sizeof(janus_text2pcap)); tp->filename = fname; tp->file = f; tp->truncate = truncate; tp->text = text; g_atomic_int_set(&tp->writable, 1); janus_mutex_init(&tp->mutex); /* If we're saving to .pcap directly, generate a global header */ if(!text) { janus_text2pcap_global_header header = { 0xa1b2c3d4, 2, 4, 0, 0, 65535, 1 }; fwrite(&header, sizeof(char), sizeof(header), f); } return tp; }
int janus_sctp_init(void) { /* Initialize the SCTP stack */ usrsctp_init(0, janus_sctp_data_to_dtls, NULL); sctp_running = TRUE; #ifdef DEBUG_SCTP JANUS_LOG(LOG_WARN, "SCTP debugging to files enabled: going to save them in %s\n", debug_folder); if(janus_mkdir(debug_folder, 0755) < 0) { JANUS_LOG(LOG_ERR, "Error creating folder %s, expect problems...\n", debug_folder); } #endif return 0; }
janus_recorder *janus_recorder_create(const char *dir, const char *codec, const char *filename) { janus_recorder_medium type = JANUS_RECORDER_AUDIO; if(codec == NULL) { JANUS_LOG(LOG_ERR, "Missing codec information\n"); return NULL; } if(!strcasecmp(codec, "vp8") || !strcasecmp(codec, "vp9") || !strcasecmp(codec, "h264")) { type = JANUS_RECORDER_VIDEO; if(!strcasecmp(codec, "vp9")) { JANUS_LOG(LOG_WARN, "The post-processor currently doesn't support VP9: recording anyway for the future\n"); } } else if(!strcasecmp(codec, "opus") || !strcasecmp(codec, "g711") || !strcasecmp(codec, "pcmu") || !strcasecmp(codec, "pcma")) { type = JANUS_RECORDER_AUDIO; if(!strcasecmp(codec, "pcmu") || !strcasecmp(codec, "pcma")) codec = "g711"; } else if(!strcasecmp(codec, "text")) { /* FIXME We only handle text on data channels, so that's the only thing we can save too */ type = JANUS_RECORDER_DATA; } else { /* We don't recognize the codec: while we might go on anyway, we'd rather fail instead */ JANUS_LOG(LOG_ERR, "Unsupported codec '%s'\n", codec); return NULL; } /* Create the recorder */ janus_recorder *rc = g_malloc0(sizeof(janus_recorder)); if(rc == NULL) { JANUS_LOG(LOG_FATAL, "Memory error!\n"); return NULL; } rc->dir = NULL; rc->filename = NULL; rc->file = NULL; rc->codec = g_strdup(codec); rc->created = janus_get_real_time(); if(dir != NULL) { /* Check if this directory exists, and create it if needed */ struct stat s; int err = stat(dir, &s); if(err == -1) { if(ENOENT == errno) { /* Directory does not exist, try creating it */ if(janus_mkdir(dir, 0755) < 0) { JANUS_LOG(LOG_ERR, "mkdir error: %d\n", errno); return NULL; } } else { JANUS_LOG(LOG_ERR, "stat error: %d\n", errno); return NULL; } } else { if(S_ISDIR(s.st_mode)) { /* Directory exists */ JANUS_LOG(LOG_VERB, "Directory exists: %s\n", dir); } else { /* File exists but it's not a directory? */ JANUS_LOG(LOG_ERR, "Not a directory? %s\n", dir); return NULL; } } } char newname[1024]; memset(newname, 0, 1024); if(filename == NULL) { /* Choose a random username */ g_snprintf(newname, 1024, "janus-recording-%"SCNu32".mjr", janus_random_uint32()); } else { /* Just append the extension */ g_snprintf(newname, 1024, "%s.mjr", filename); } /* Try opening the file now */ if(dir == NULL) { rc->file = fopen(newname, "wb"); } else { char path[1024]; memset(path, 0, 1024); g_snprintf(path, 1024, "%s/%s", dir, newname); rc->file = fopen(path, "wb"); } if(rc->file == NULL) { JANUS_LOG(LOG_ERR, "fopen error: %d\n", errno); return NULL; } if(dir) rc->dir = g_strdup(dir); rc->filename = g_strdup(newname); rc->type = type; /* Write the first part of the header */ fwrite(header, sizeof(char), strlen(header), rc->file); rc->writable = 1; /* We still need to also write the info header first */ rc->header = 0; janus_mutex_init(&rc->mutex); return rc; }
janus_recorder *janus_recorder_create(const char *dir, const char *codec, const char *filename) { janus_recorder_medium type = JANUS_RECORDER_AUDIO; if(codec == NULL) { JANUS_LOG(LOG_ERR, "Missing codec information\n"); return NULL; } if(!strcasecmp(codec, "vp8") || !strcasecmp(codec, "vp9") || !strcasecmp(codec, "h264")) { type = JANUS_RECORDER_VIDEO; } else if(!strcasecmp(codec, "opus") || !strcasecmp(codec, "g711") || !strcasecmp(codec, "pcmu") || !strcasecmp(codec, "pcma") || !strcasecmp(codec, "g722")) { type = JANUS_RECORDER_AUDIO; } else if(!strcasecmp(codec, "text")) { /* FIXME We only handle text on data channels, so that's the only thing we can save too */ type = JANUS_RECORDER_DATA; } else { /* We don't recognize the codec: while we might go on anyway, we'd rather fail instead */ JANUS_LOG(LOG_ERR, "Unsupported codec '%s'\n", codec); return NULL; } /* Create the recorder */ janus_recorder *rc = g_malloc0(sizeof(janus_recorder)); rc->dir = NULL; rc->filename = NULL; rc->file = NULL; rc->codec = g_strdup(codec); rc->created = janus_get_real_time(); const char *rec_dir = NULL; const char *rec_file = NULL; char *copy_for_parent = NULL; char *copy_for_base = NULL; /* Check dir and filename values */ if (filename != NULL) { /* Helper copies to avoid overwriting */ copy_for_parent = g_strdup(filename); copy_for_base = g_strdup(filename); /* Get filename parent folder */ const char *filename_parent = dirname(copy_for_parent); /* Get filename base file */ const char *filename_base = basename(copy_for_base); if (!dir) { /* If dir is NULL we have to create filename_parent and filename_base */ rec_dir = filename_parent; rec_file = filename_base; } else { /* If dir is valid we have to create dir and filename*/ rec_dir = dir; rec_file = filename; if (strcasecmp(filename_parent, ".") || strcasecmp(filename_base, filename)) { JANUS_LOG(LOG_WARN, "Unsupported combination of dir and filename %s %s\n", dir, filename); } } } if(rec_dir != NULL) { /* Check if this directory exists, and create it if needed */ struct stat s; int err = stat(rec_dir, &s); if(err == -1) { if(ENOENT == errno) { /* Directory does not exist, try creating it */ if(janus_mkdir(rec_dir, 0755) < 0) { JANUS_LOG(LOG_ERR, "mkdir error: %d\n", errno); return NULL; } } else { JANUS_LOG(LOG_ERR, "stat error: %d\n", errno); return NULL; } } else { if(S_ISDIR(s.st_mode)) { /* Directory exists */ JANUS_LOG(LOG_VERB, "Directory exists: %s\n", rec_dir); } else { /* File exists but it's not a directory? */ JANUS_LOG(LOG_ERR, "Not a directory? %s\n", rec_dir); return NULL; } } } char newname[1024]; memset(newname, 0, 1024); if(rec_file == NULL) { /* Choose a random username */ if(!rec_tempname) { /* Use .mjr as an extension right away */ g_snprintf(newname, 1024, "janus-recording-%"SCNu32".mjr", janus_random_uint32()); } else { /* Append the temporary extension to .mjr, we'll rename when closing */ g_snprintf(newname, 1024, "janus-recording-%"SCNu32".mjr.%s", janus_random_uint32(), rec_tempext); } } else { /* Just append the extension */ if(!rec_tempname) { /* Use .mjr as an extension right away */ g_snprintf(newname, 1024, "%s.mjr", rec_file); } else { /* Append the temporary extension to .mjr, we'll rename when closing */ g_snprintf(newname, 1024, "%s.mjr.%s", rec_file, rec_tempext); } } /* Try opening the file now */ if(rec_dir == NULL) { rc->file = fopen(newname, "wb"); } else { char path[1024]; memset(path, 0, 1024); g_snprintf(path, 1024, "%s/%s", rec_dir, newname); rc->file = fopen(path, "wb"); } if(rc->file == NULL) { JANUS_LOG(LOG_ERR, "fopen error: %d\n", errno); return NULL; } if(rec_dir) rc->dir = g_strdup(rec_dir); rc->filename = g_strdup(newname); rc->type = type; /* Write the first part of the header */ fwrite(header, sizeof(char), strlen(header), rc->file); g_atomic_int_set(&rc->writable, 1); /* We still need to also write the info header first */ g_atomic_int_set(&rc->header, 0); janus_mutex_init(&rc->mutex); /* Done */ g_atomic_int_set(&rc->destroyed, 0); janus_refcount_init(&rc->ref, janus_recorder_free); g_free(copy_for_parent); g_free(copy_for_base); return rc; }
gboolean janus_config_save(janus_config *config, const char *folder, const char *filename) { if(config == NULL) return -1; FILE *file = NULL; char path[1024]; if(folder != NULL) { /* Create folder, if needed */ if(janus_mkdir(folder, 0755) < 0) { JANUS_LOG(LOG_ERR, "Couldn't save configuration file, error creating folder '%s'...\n", folder); return -2; } g_snprintf(path, 1024, "%s/%s.cfg", folder, filename); } else { g_snprintf(path, 1024, "%s.cfg", filename); } file = fopen(path, "wt"); if(file == NULL) { JANUS_LOG(LOG_ERR, "Couldn't save configuration file, error opening file '%s'...\n", path); return -3; } /* Print a header */ char date[64], header[256]; struct tm tmresult; time_t ltime = time(NULL); localtime_r(<ime, &tmresult); strftime(date, sizeof(date), "%a %b %e %T %Y", &tmresult); g_snprintf(header, 256, ";\n; File automatically generated on %s\n;\n\n", date); fwrite(header, sizeof(char), strlen(header), file); /* Go on with the configuration */ if(config->items) { GList *l = config->items; while(l) { janus_config_item *i = (janus_config_item *)l->data; if(i->name && i->value) { fwrite(i->name, sizeof(char), strlen(i->name), file); fwrite(" = ", sizeof(char), 3, file); fwrite(i->value, sizeof(char), strlen(i->value), file); fwrite("\n", sizeof(char), 1, file); } l = l->next; } } if(config->categories) { GList *l = config->categories; while(l) { janus_config_category *c = (janus_config_category *)l->data; if(c->name) { fwrite("[", sizeof(char), 1, file); fwrite(c->name, sizeof(char), strlen(c->name), file); fwrite("]\n", sizeof(char), 2, file); if(c->items) { GList *li = c->items; while(li) { janus_config_item *i = (janus_config_item *)li->data; if(i->name && i->value) { fwrite(i->name, sizeof(char), strlen(i->name), file); fwrite(" = ", sizeof(char), 3, file); /* If the value contains a semicolon, escape it */ if(strchr(i->value, ';')) { char *value = g_strdup(i->value); value = janus_string_replace((char *)value, ";", "\\;"); fwrite(value, sizeof(char), strlen(value), file); fwrite("\n", sizeof(char), 1, file); g_free(value); } else { /* No need to escape */ fwrite(i->value, sizeof(char), strlen(i->value), file); fwrite("\n", sizeof(char), 1, file); } } li = li->next; } } } fwrite("\r\n", sizeof(char), 2, file); l = l->next; } } fclose(file); return 0; }