コード例 #1
0
ファイル: config.c プロジェクト: indutny/bud
bud_error_t bud_config_load(bud_config_t* config) {
  int i;
  bud_error_t err;
  JSON_Value* json;
  JSON_Value* val;
  JSON_Object* frontend;
  JSON_Object* obj;
  JSON_Object* log;
  JSON_Object* avail;
  JSON_Array* contexts;

  if (config->piped) {
    char* content;

    ASSERT(config->loop != NULL, "Loop should be present");
    err = bud_read_file_by_fd(config->loop, 0, &content);
    if (!bud_is_ok(err))
      goto end;

    err = bud_hashmap_insert(&config->files.hashmap,
                             kPipedConfigPath,
                             strlen(kPipedConfigPath),
                             content);
    if (!bud_is_ok(err)) {
      free(content);
      goto end;
    }

    json = json_parse_string(content);
  } else if (config->inlined) {
    json = json_parse_string(config->path);
  } else {
    const char* contents;

    err = bud_config_load_file(config, config->path, &contents);
    if (!bud_is_ok(err))
      goto end;
    json = json_parse_string(contents);
  }

  if (json == NULL) {
    err = bud_error_dstr(kBudErrJSONParse, config->path);
    goto end;
  }

  obj = json_value_get_object(json);
  if (obj == NULL) {
    err = bud_error(kBudErrJSONNonObjectRoot);
    goto failed_alloc_path;
  }

  err = bud_config_load_tracing(&config->trace,
                                json_object_get_object(obj, "tracing"));
  if (!bud_is_ok(err))
    goto failed_alloc_path;

  /* Allocate contexts and backends */
  contexts = json_object_get_array(obj, "contexts");
  config->context_count = contexts == NULL ? 0 : json_array_get_count(contexts);
  config->contexts = calloc(config->context_count + 1,
                            sizeof(*config->contexts));
  if (config->contexts == NULL) {
    err = bud_error_str(kBudErrNoMem, "bud_context_t");
    goto failed_alloc_contexts;
  }

  config->json = json;

  /* Workers configuration */
  config->worker_count = -1;
  config->restart_timeout = -1;
  config->master_ipc = -1;
  val = json_object_get_value(obj, "workers");
  if (val != NULL)
    config->worker_count = json_value_get_number(val);
  val = json_object_get_value(obj, "restart_timeout");
  if (val != NULL)
    config->restart_timeout = json_value_get_number(val);
  val = json_object_get_value(obj, "master_ipc");
  if (val != NULL)
    config->master_ipc = json_value_get_boolean(val);

  /* Logger configuration */
  log = json_object_get_object(obj, "log");
  config->log.stdio = -1;
  config->log.syslog = -1;
  if (log != NULL) {
    config->log.level = json_object_get_string(log, "level");
    config->log.facility = json_object_get_string(log, "facility");

    val = json_object_get_value(log, "stdio");
    if (val != NULL)
      config->log.stdio = json_value_get_boolean(val);
    val = json_object_get_value(log, "syslog");
    if (val != NULL)
      config->log.syslog = json_value_get_boolean(val);
  }

  /* Availability configuration */
  avail = json_object_get_object(obj, "availability");
  config->availability.death_timeout = -1;
  config->availability.revive_interval = -1;
  config->availability.retry_interval = -1;
  config->availability.max_retries = -1;
  if (avail != NULL) {
    val = json_object_get_value(avail, "death_timeout");
    if (val != NULL)
      config->availability.death_timeout = json_value_get_number(val);
    val = json_object_get_value(avail, "revive_interval");
    if (val != NULL)
      config->availability.revive_interval = json_value_get_number(val);
    val = json_object_get_value(avail, "retry_interval");
    if (val != NULL)
      config->availability.retry_interval = json_value_get_number(val);
    val = json_object_get_value(avail, "max_retries");
    if (val != NULL)
      config->availability.max_retries = json_value_get_number(val);
  }

  /* Frontend configuration */
  frontend = json_object_get_object(obj, "frontend");
  err = bud_config_load_frontend(frontend, &config->frontend);
  if (!bud_is_ok(err))
    goto failed_alloc_contexts;

  /* Load frontend's context */
  err = bud_context_load(frontend, &config->contexts[0]);
  if (!bud_is_ok(err))
    goto failed_alloc_contexts;

  /* Backend configuration */
  config->balance = json_object_get_string(obj, "balance");
  err = bud_config_load_backend_list(config,
                                      obj,
                                      &config->contexts[0].backend);
  if (!bud_is_ok(err))
    goto failed_alloc_contexts;

  /* User and group configuration */
  config->user = json_object_get_string(obj, "user");
  config->group = json_object_get_string(obj, "group");

  /* SNI configuration */
  bud_config_read_pool_conf(obj, "sni", &config->sni);

  /* OCSP Stapling configuration */
  bud_config_read_pool_conf(obj, "stapling", &config->stapling);

  /* SSL Contexts */

  /* TODO(indutny): sort them and do binary search */
  for (i = 0; i < config->context_count; i++) {
    bud_context_t* ctx;

    /* NOTE: contexts[0] - is a default context */
    ctx = &config->contexts[i + 1];
    obj = json_array_get_object(contexts, i);
    if (obj == NULL) {
      err = bud_error(kBudErrJSONNonObjectCtx);
      goto failed_load_context;
    }

    err = bud_context_load(obj, ctx);
    if (!bud_is_ok(err))
      goto failed_load_context;

    err = bud_config_load_backend_list(config, obj, &ctx->backend);
    if (!bud_is_ok(err))
      goto failed_load_context;
  }

  bud_config_set_defaults(config);

  return bud_config_init(config);

failed_load_context:
  /* Deinitalize contexts */
  for (i++; i >= 0; i--) {
    bud_context_t* ctx;

    ctx = &config->contexts[i];
    free(ctx->backend.list);
    ctx->backend.list = NULL;
  }

failed_alloc_contexts:
  free(config->contexts);
  config->contexts = NULL;
  free(config->trace.dso);
  config->trace.dso = NULL;

failed_alloc_path:
  json_value_free(json);
  config->json = NULL;

end:
  return err;
}
コード例 #2
0
bud_config_t* bud_config_load(const char* path, int inlined, bud_error_t* err) {
  int i;
  JSON_Value* json;
  JSON_Value* val;
  JSON_Object* obj;
  JSON_Object* tmp;
  JSON_Object* log;
  JSON_Object* avail;
  JSON_Array* contexts;
  JSON_Array* backend;
  bud_config_t* config;
  bud_context_t* ctx;

  if (inlined)
    json = json_parse_string(path);
  else
    json = json_parse_file(path);

  if (json == NULL) {
    *err = bud_error_str(kBudErrJSONParse, path);
    goto end;
  }

  obj = json_value_get_object(json);
  if (obj == NULL) {
    *err = bud_error(kBudErrJSONNonObjectRoot);
    goto failed_get_object;
  }

  config = calloc(1, sizeof(*config));
  if (config == NULL) {
    *err = bud_error_str(kBudErrNoMem, "bud_config_t");
    goto failed_get_object;
  }

  /* Copy path or inlined config value */
  config->path = strdup(path);
  if (config->path == NULL) {
    *err = bud_error_str(kBudErrNoMem, "bud_config_t strcpy(path)");
    goto failed_alloc_path;
  }

  config->inlined = inlined;

  /* Allocate contexts and backends */
  contexts = json_object_get_array(obj, "contexts");
  backend = json_object_get_array(obj, "backend");
  config->context_count = contexts == NULL ? 0 : json_array_get_count(contexts);
  config->backend_count = backend == NULL ? 0 : json_array_get_count(backend);
  config->contexts = calloc(config->context_count + 1,
                            sizeof(*config->contexts));
  config->backend = calloc(config->backend_count, sizeof(*config->backend));

  if (config->contexts == NULL || config->backend == NULL) {
    *err = bud_error_str(kBudErrNoMem, "bud_context_t");
    goto failed_get_index;
  }

  config->json = json;

  /* Workers configuration */
  config->worker_count = -1;
  config->restart_timeout = -1;
  val = json_object_get_value(obj, "workers");
  if (val != NULL)
    config->worker_count = json_value_get_number(val);
  val = json_object_get_value(obj, "restart_timeout");
  if (val != NULL)
    config->restart_timeout = json_value_get_number(val);

  /* Logger configuration */
  log = json_object_get_object(obj, "log");
  config->log.stdio = -1;
  config->log.syslog = -1;
  if (log != NULL) {
    config->log.level = json_object_get_string(log, "level");
    config->log.facility = json_object_get_string(log, "facility");

    val = json_object_get_value(log, "stdio");
    if (val != NULL)
      config->log.stdio = json_value_get_boolean(val);
    val = json_object_get_value(log, "syslog");
    if (val != NULL)
      config->log.syslog = json_value_get_boolean(val);
  }

  /* Availability configuration */
  avail = json_object_get_object(obj, "availability");
  config->availability.death_timeout = -1;
  config->availability.revive_interval = -1;
  config->availability.retry_interval = -1;
  config->availability.max_retries = -1;
  if (avail != NULL) {
    val = json_object_get_value(avail, "death_timeout");
    if (val != NULL)
      config->availability.death_timeout = json_value_get_number(val);
    val = json_object_get_value(avail, "revive_interval");
    if (val != NULL)
      config->availability.revive_interval = json_value_get_number(val);
    val = json_object_get_value(avail, "retry_interval");
    if (val != NULL)
      config->availability.retry_interval = json_value_get_number(val);
    val = json_object_get_value(avail, "max_retries");
    if (val != NULL)
      config->availability.max_retries = json_value_get_number(val);
  }

  /* Frontend configuration */
  *err = bud_config_load_frontend(json_object_get_object(obj, "frontend"),
                                  &config->frontend);
  if (!bud_is_ok(*err))
    goto failed_get_index;

  /* Backend configuration */
  config->balance = json_object_get_string(obj, "balance");
  for (i = 0; i < config->backend_count; i++) {
    bud_config_load_backend(config,
                            json_array_get_object(backend, i),
                            &config->backend[i]);
  }

  /* SNI configuration */
  bud_config_read_pool_conf(obj, "sni", &config->sni);

  /* OCSP Stapling configuration */
  bud_config_read_pool_conf(obj, "stapling", &config->stapling);

  /* SSL Contexts */

  /* TODO(indutny): sort them and do binary search */
  for (i = 0; i < config->context_count; i++) {
    /* NOTE: contexts[0] - is a default context */
    ctx = &config->contexts[i + 1];
    obj = json_array_get_object(contexts, i);
    if (obj == NULL) {
      *err = bud_error(kBudErrJSONNonObjectCtx);
      goto failed_get_index;
    }

    ctx->servername = json_object_get_string(obj, "servername");
    ctx->servername_len = ctx->servername == NULL ? 0 : strlen(ctx->servername);
    ctx->cert_file = json_object_get_string(obj, "cert");
    ctx->key_file = json_object_get_string(obj, "key");
    ctx->npn = json_object_get_array(obj, "npn");
    ctx->ciphers = json_object_get_string(obj, "ciphers");
    ctx->ecdh = json_object_get_string(obj, "ecdh");
    ctx->ticket_key = json_object_get_string(obj, "ticket_key");

    tmp = json_object_get_object(obj, "backend");
    if (tmp != NULL) {
      ctx->backend = &ctx->backend_st;
      bud_config_load_backend(config, tmp, ctx->backend);
    }

    *err = bud_config_verify_npn(ctx->npn);
    if (!bud_is_ok(*err))
      goto failed_get_index;
  }

  bud_config_set_defaults(config);

  *err = bud_ok();
  return config;

failed_get_index:
  free(config->contexts);
  config->contexts = NULL;
  free(config->backend);
  config->backend = NULL;
  free(config->path);
  config->path = NULL;

failed_alloc_path:
  free(config);

failed_get_object:
  json_value_free(json);

end:
  return NULL;
}