bud_error_t bud_config_load_frontend(JSON_Object* obj, bud_config_frontend_t* frontend) { bud_error_t err; JSON_Value* val; bud_config_load_addr(obj, (bud_config_addr_t*) frontend); frontend->server_preference = -1; frontend->ssl3 = -1; frontend->max_send_fragment = -1; frontend->allow_half_open = -1; if (obj == NULL) return bud_ok(); frontend->security = json_object_get_string(obj, "security"); frontend->ciphers = json_object_get_string(obj, "ciphers"); frontend->ecdh = json_object_get_string(obj, "ecdh"); frontend->cert_file = json_object_get_string(obj, "cert"); frontend->key_file = json_object_get_string(obj, "key"); frontend->reneg_window = json_object_get_number(obj, "reneg_window"); frontend->reneg_limit = json_object_get_number(obj, "reneg_limit"); frontend->ticket_key = json_object_get_string(obj, "ticket_key"); /* Get and verify NPN */ frontend->npn = json_object_get_array(obj, "npn"); err = bud_config_verify_npn(frontend->npn); if (!bud_is_ok(err)) goto fatal; val = json_object_get_value(obj, "server_preference"); if (val != NULL) frontend->server_preference = json_value_get_boolean(val); val = json_object_get_value(obj, "ssl3"); if (val != NULL) frontend->ssl3 = json_value_get_boolean(val); val = json_object_get_value(obj, "max_send_fragment"); if (val != NULL) frontend->max_send_fragment = json_value_get_number(val); val = json_object_get_value(obj, "allow_half_open"); if (val != NULL) frontend->allow_half_open = json_value_get_boolean(val); fatal: return err; }
bud_config_t* bud_config_load(uv_loop_t* loop, const char* path, bud_error_t* err) { int i; int context_count; JSON_Value* json; JSON_Value* val; JSON_Object* obj; JSON_Object* log; JSON_Object* frontend; JSON_Object* backend; JSON_Array* contexts; bud_config_t* config; bud_context_t* ctx; 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; } contexts = json_object_get_array(obj, "contexts"); context_count = contexts == NULL ? 0 : json_array_get_count(contexts); config = calloc(1, sizeof(*config) + context_count * sizeof(*config->contexts)); if (config == NULL) { *err = bud_error_str(kBudErrNoMem, "bud_config_t"); goto failed_get_object; } config->loop = loop; 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); } /* Frontend configuration */ frontend = json_object_get_object(obj, "frontend"); config->frontend.proxyline = -1; config->frontend.keepalive = -1; config->frontend.server_preference = -1; config->frontend.ssl3 = -1; if (frontend != NULL) { config->frontend.port = (uint16_t) json_object_get_number(frontend, "port"); config->frontend.host = json_object_get_string(frontend, "host"); config->frontend.security = json_object_get_string(frontend, "security"); config->frontend.npn = json_object_get_array(frontend, "npn"); config->frontend.ciphers = json_object_get_string(frontend, "ciphers"); config->frontend.cert_file = json_object_get_string(frontend, "cert"); config->frontend.key_file = json_object_get_string(frontend, "key"); config->frontend.reneg_window = json_object_get_number(frontend, "reneg_window"); config->frontend.reneg_limit = json_object_get_number(frontend, "reneg_limit"); *err = bud_config_verify_npn(config->frontend.npn); if (!bud_is_ok(*err)) goto failed_get_index; val = json_object_get_value(frontend, "proxyline"); if (val != NULL) config->frontend.proxyline = json_value_get_boolean(val); val = json_object_get_value(frontend, "keepalive"); if (val != NULL) config->frontend.keepalive = json_value_get_number(val); val = json_object_get_value(frontend, "server_preference"); if (val != NULL) config->frontend.server_preference = json_value_get_boolean(val); val = json_object_get_value(frontend, "ssl3"); if (val != NULL) config->frontend.ssl3 = json_value_get_boolean(val); } /* Backend configuration */ backend = json_object_get_object(obj, "backend"); config->backend.keepalive = -1; if (backend != NULL) { config->backend.port = (uint16_t) json_object_get_number(backend, "port"); config->backend.host = json_object_get_string(backend, "host"); val = json_object_get_value(backend, "keepalive"); if (val != NULL) config->backend.keepalive = json_value_get_number(val); } /* 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 < 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"); *err = bud_config_verify_npn(ctx->npn); if (!bud_is_ok(*err)) goto failed_get_index; } config->context_count = context_count; bud_config_set_defaults(config); *err = bud_ok(); return config; failed_get_index: free(config); failed_get_object: json_value_free(json); end: return NULL; }
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; }