324 lines
9.9 KiB
C
324 lines
9.9 KiB
C
#define TRACE_MODULE _context
|
|
|
|
#include "core_file.h"
|
|
#include "core_debug.h"
|
|
#include "core_lib.h"
|
|
#include "core_pkbuf.h"
|
|
|
|
#include <mongoc.h>
|
|
#include <yaml.h>
|
|
#include "yaml_helper.h"
|
|
|
|
#include "context.h"
|
|
|
|
static context_t self;
|
|
|
|
static int context_initialized = 0;
|
|
|
|
status_t context_init()
|
|
{
|
|
d_assert(context_initialized == 0, return CORE_ERROR,
|
|
"Context already has been context_initialized");
|
|
|
|
memset(&self, 0, sizeof(context_t));
|
|
|
|
context_initialized = 1;
|
|
|
|
return CORE_OK;
|
|
}
|
|
|
|
status_t context_final()
|
|
{
|
|
d_assert(context_initialized == 1, return CORE_ERROR,
|
|
"Context already has been finalized");
|
|
|
|
if (self.config.document)
|
|
{
|
|
yaml_document_delete(self.config.document);
|
|
core_free(self.config.document);
|
|
}
|
|
|
|
context_initialized = 0;
|
|
|
|
return CORE_OK;
|
|
}
|
|
|
|
context_t* context_self()
|
|
{
|
|
return &self;
|
|
}
|
|
|
|
status_t context_read_file()
|
|
{
|
|
config_t *config = &self.config;
|
|
FILE *file;
|
|
yaml_parser_t parser;
|
|
yaml_document_t *document = NULL;
|
|
|
|
d_assert(config->path, return CORE_ERROR,);
|
|
|
|
file = fopen(config->path, "rb");
|
|
d_assert(file, return CORE_ERROR,);
|
|
|
|
d_assert(yaml_parser_initialize(&parser), return CORE_ERROR,);
|
|
yaml_parser_set_input_file(&parser, file);
|
|
|
|
document = core_calloc(1, sizeof(yaml_document_t));
|
|
if (!yaml_parser_load(&parser, document))
|
|
{
|
|
d_fatal("Failed to parse configuration file '%s'", config->path);
|
|
core_free(document);
|
|
return CORE_ERROR;
|
|
}
|
|
|
|
config->document = document;
|
|
|
|
yaml_parser_delete(&parser);
|
|
d_assert(!fclose(file),,);
|
|
|
|
return CORE_OK;
|
|
}
|
|
|
|
static status_t context_prepare()
|
|
{
|
|
self.logger.console = -1;
|
|
|
|
return CORE_OK;
|
|
}
|
|
|
|
static status_t context_validation()
|
|
{
|
|
if (self.parameter.no_ipv4 == 1 && self.parameter.no_ipv6 == 1)
|
|
{
|
|
d_error("Both `no_ipv4` and `no_ipv6` set to `true` in `%s`",
|
|
context_self()->config.path);
|
|
return CORE_ERROR;
|
|
}
|
|
|
|
return CORE_OK;
|
|
}
|
|
status_t context_parse_config()
|
|
{
|
|
status_t rv;
|
|
config_t *config = &self.config;
|
|
yaml_document_t *document = NULL;
|
|
yaml_iter_t root_iter;
|
|
|
|
d_assert(config, return CORE_ERROR,);
|
|
document = config->document;
|
|
d_assert(document, return CORE_ERROR,);
|
|
|
|
rv = context_prepare();
|
|
if (rv != CORE_OK) return rv;
|
|
|
|
yaml_iter_init(&root_iter, document);
|
|
while(yaml_iter_next(&root_iter))
|
|
{
|
|
const char *root_key = yaml_iter_key(&root_iter);
|
|
d_assert(root_key, return CORE_ERROR,);
|
|
if (!strcmp(root_key, "db_uri"))
|
|
{
|
|
self.db_uri = yaml_iter_value(&root_iter);
|
|
}
|
|
else if (!strcmp(root_key, "logger"))
|
|
{
|
|
yaml_iter_t logger_iter;
|
|
yaml_iter_recurse(&root_iter, &logger_iter);
|
|
while(yaml_iter_next(&logger_iter))
|
|
{
|
|
const char *logger_key = yaml_iter_key(&logger_iter);
|
|
d_assert(logger_key, return CORE_ERROR,);
|
|
if (!strcmp(logger_key, "file"))
|
|
{
|
|
self.logger.file = yaml_iter_value(&logger_iter);
|
|
}
|
|
else if (!strcmp(logger_key, "console"))
|
|
{
|
|
const char *v = yaml_iter_value(&logger_iter);
|
|
if (v) self.logger.console = atoi(v);
|
|
}
|
|
else if (!strcmp(logger_key, "syslog"))
|
|
{
|
|
self.logger.syslog = yaml_iter_value(&logger_iter);
|
|
}
|
|
else if (!strcmp(logger_key, "network"))
|
|
{
|
|
yaml_iter_t network_iter;
|
|
yaml_iter_recurse(&logger_iter, &network_iter);
|
|
while(yaml_iter_next(&network_iter))
|
|
{
|
|
const char *network_key = yaml_iter_key(&network_iter);
|
|
d_assert(network_key, return CORE_ERROR,);
|
|
if (!strcmp(network_key, "file"))
|
|
{
|
|
self.logger.network.file =
|
|
yaml_iter_value(&network_iter);
|
|
}
|
|
else if (!strcmp(network_key, "unixDomain"))
|
|
{
|
|
self.logger.network.unix_domain =
|
|
yaml_iter_value(&network_iter);
|
|
}
|
|
else
|
|
d_warn("unknown key `%s`", network_key);
|
|
}
|
|
}
|
|
else if (!strcmp(logger_key, "trace"))
|
|
{
|
|
yaml_iter_t trace_iter;
|
|
yaml_iter_recurse(&logger_iter, &trace_iter);
|
|
while(yaml_iter_next(&trace_iter))
|
|
{
|
|
const char *trace_key = yaml_iter_key(&trace_iter);
|
|
d_assert(trace_key, return CORE_ERROR,);
|
|
if (!strcmp(trace_key, "s1ap"))
|
|
{
|
|
const char *v = yaml_iter_value(&trace_iter);
|
|
if (v) self.logger.trace.s1ap = atoi(v);
|
|
}
|
|
else if (!strcmp(trace_key, "nas"))
|
|
{
|
|
const char *v = yaml_iter_value(&trace_iter);
|
|
if (v) self.logger.trace.nas = atoi(v);
|
|
}
|
|
else if (!strcmp(trace_key, "diameter"))
|
|
{
|
|
const char *v = yaml_iter_value(&trace_iter);
|
|
if (v) self.logger.trace.diameter = atoi(v);
|
|
}
|
|
else if (!strcmp(trace_key, "gtp"))
|
|
{
|
|
const char *v = yaml_iter_value(&trace_iter);
|
|
if (v) self.logger.trace.gtp = atoi(v);
|
|
}
|
|
else if (!strcmp(trace_key, "others"))
|
|
{
|
|
const char *v = yaml_iter_value(&trace_iter);
|
|
if (v) self.logger.trace.others = atoi(v);
|
|
}
|
|
else
|
|
d_warn("unknown key `%s`", trace_key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (!strcmp(root_key, "parameter"))
|
|
{
|
|
yaml_iter_t parameter_iter;
|
|
yaml_iter_recurse(&root_iter, ¶meter_iter);
|
|
while(yaml_iter_next(¶meter_iter))
|
|
{
|
|
const char *parameter_key = yaml_iter_key(¶meter_iter);
|
|
d_assert(parameter_key, return CORE_ERROR,);
|
|
if (!strcmp(parameter_key, "no_hss"))
|
|
{
|
|
self.parameter.no_hss =
|
|
yaml_iter_bool(¶meter_iter);
|
|
}
|
|
else if (!strcmp(parameter_key, "no_sgw"))
|
|
{
|
|
self.parameter.no_sgw =
|
|
yaml_iter_bool(¶meter_iter);
|
|
}
|
|
else if (!strcmp(parameter_key, "no_pgw"))
|
|
{
|
|
self.parameter.no_pgw =
|
|
yaml_iter_bool(¶meter_iter);
|
|
}
|
|
else if (!strcmp(parameter_key, "no_pcrf"))
|
|
{
|
|
self.parameter.no_pcrf =
|
|
yaml_iter_bool(¶meter_iter);
|
|
}
|
|
else if (!strcmp(parameter_key, "no_ipv4"))
|
|
{
|
|
self.parameter.no_ipv4 =
|
|
yaml_iter_bool(¶meter_iter);
|
|
}
|
|
else if (!strcmp(parameter_key, "no_ipv6"))
|
|
{
|
|
self.parameter.no_ipv6 =
|
|
yaml_iter_bool(¶meter_iter);
|
|
}
|
|
else if (!strcmp(parameter_key, "prefer_ipv4"))
|
|
{
|
|
self.parameter.prefer_ipv4 =
|
|
yaml_iter_bool(¶meter_iter);
|
|
}
|
|
else
|
|
d_warn("unknown key `%s`", parameter_key);
|
|
}
|
|
}
|
|
}
|
|
|
|
rv = context_validation();
|
|
if (rv != CORE_OK) return rv;
|
|
|
|
return CORE_OK;
|
|
}
|
|
|
|
status_t context_db_init(const char *db_uri)
|
|
{
|
|
bson_t reply;
|
|
bson_error_t error;
|
|
bson_iter_t iter;
|
|
|
|
const mongoc_uri_t *uri;
|
|
|
|
mongoc_init();
|
|
|
|
self.db_client = mongoc_client_new(db_uri);
|
|
if (!self.db_client)
|
|
{
|
|
d_error("Failed to parse DB URI [%s]", db_uri);
|
|
return CORE_ERROR;
|
|
}
|
|
|
|
#if MONGOC_MAJOR_VERSION >= 1 && MONGOC_MINOR_VERSION >= 4
|
|
mongoc_client_set_error_api(self.db_client, 2);
|
|
#endif
|
|
|
|
uri = mongoc_client_get_uri(self.db_client);
|
|
d_assert(uri, context_db_final(); return CORE_ERROR,
|
|
"Database is not defined in DB_URI [%s]", db_uri);
|
|
|
|
self.db_name = (char *)mongoc_uri_get_database(uri);
|
|
d_assert(self.db_name, context_db_final(); return CORE_ERROR,
|
|
"Database is not defined in DB_URI [%s]", db_uri);
|
|
|
|
self.database = mongoc_client_get_database(self.db_client, self.db_name);
|
|
d_assert(self.database, context_db_final(); return CORE_ERROR,
|
|
"Database is not defined in DB_URI [%s]", db_uri);
|
|
|
|
if (!mongoc_client_get_server_status(self.db_client, NULL, &reply, &error))
|
|
{
|
|
d_error("Failed to conect to server [%s]", db_uri);
|
|
return CORE_EAGAIN;
|
|
}
|
|
|
|
d_assert(bson_iter_init_find(&iter, &reply, "ok"),
|
|
bson_destroy(&reply); context_db_final(); return CORE_ERROR,
|
|
"Invalid reply for server status [%s]", db_uri);
|
|
|
|
bson_destroy(&reply);
|
|
return CORE_OK;
|
|
}
|
|
|
|
status_t context_db_final()
|
|
{
|
|
if (self.database)
|
|
{
|
|
mongoc_database_destroy(self.database);
|
|
self.database = NULL;
|
|
}
|
|
if (self.db_client)
|
|
{
|
|
mongoc_client_destroy(self.db_client);
|
|
self.db_client = NULL;
|
|
}
|
|
|
|
mongoc_cleanup();
|
|
|
|
return CORE_OK;
|
|
}
|