LLVMFuzzerTestOneInput:
  497|     24|{
  498|     24|#if defined(TEST_FUZZ1)
  499|       |	/* fuzz target 1: different URI for HTTP/1 server */
  500|     24|	return LLVMFuzzerTestOneInput_URI(data, size);
  501|       |#elif defined(TEST_FUZZ2)
  502|       |	/* fuzz target 2: different requests for HTTP/1 server */
  503|       |	return LLVMFuzzerTestOneInput_REQUEST(data, size);
  504|       |#elif defined(TEST_FUZZ3)
  505|       |	/* fuzz target 3: different responses for HTTP/1 client */
  506|       |	return LLVMFuzzerTestOneInput_RESPONSE(data, size);
  507|       |#elif defined(TEST_FUZZ4)
  508|       |#error "Only useful in HTTP/2 feature branch"
  509|       |	/* fuzz target 4: different requests for HTTP/2 server */
  510|       |	return LLVMFuzzerTestOneInput_REQUEST_HTTP2(data, size);
  511|       |#elif defined(TEST_FUZZ5)
  512|       |	/* fuzz target 5: calling an internal server test function,
  513|       |	 *                bypassing network sockets */
  514|       |	return LLVMFuzzerTestOneInput_process_new_connection(data, size);
  515|       |#else
  516|       |/* planned targets */
  517|       |#error "Unknown fuzz target"
  518|       |#endif
  519|     24|}
fuzzmain.c:LLVMFuzzerTestOneInput_URI:
  208|     24|{
  209|     24|	static char URI[1024 * 64]; /* static, to avoid stack overflow */
  210|       |
  211|     24|	if (call_count == 0) {
  ------------------
  |  Branch (211:6): [True: 1, False: 23]
  ------------------
  212|      1|		memset(URI, 0, sizeof(URI));
  213|      1|		civetweb_init();
  214|      1|	}
  215|     24|	call_count++;
  216|       |
  217|     24|	if (size < sizeof(URI)) {
  ------------------
  |  Branch (217:6): [True: 0, False: 24]
  ------------------
  218|      0|		memcpy(URI, data, size);
  219|      0|		URI[size] = 0;
  220|     24|	} else {
  221|     24|		return 1;
  222|     24|	}
  223|       |
  224|      0|	return test_civetweb_client("127.0.0.1", PORT_NUM_HTTP, 0, URI);
  225|     24|}
fuzzmain.c:civetweb_init:
   76|      1|{
   77|      1|	struct mg_callbacks callbacks;
   78|      1|	struct mg_server_port ports[8];
   79|      1|	memset(&callbacks, 0, sizeof(callbacks));
   80|      1|	memset(&ports, 0, sizeof(ports));
   81|       |
   82|      1|	ctx = mg_start(&callbacks, 0, OPTIONS);
   83|       |
   84|      1|	if (!ctx) {
  ------------------
  |  Branch (84:6): [True: 0, False: 1]
  ------------------
   85|      0|		fprintf(stderr, "\nCivetWeb test server failed to start\n");
   86|      0|		TESTabort();
  ------------------
  |  |   41|      0|	{                                                                          \
  |  |   42|      0|		fprintf(stderr, "!!! Precondition in test environment not met !!!\n"); \
  |  |   43|      0|		fprintf(stderr, "!!! aborting fuzz test in line %u !!!", __LINE__);    \
  |  |   44|      0|		abort();                                                               \
  |  |   45|      0|	}
  ------------------
   87|      0|	}
   88|       |
   89|      1|	int ret = mg_get_server_ports(ctx, 8, ports);
   90|      1|	if (ret != 1) {
  ------------------
  |  Branch (90:6): [True: 0, False: 1]
  ------------------
   91|      0|		fprintf(stderr,
   92|      0|		        "\nCivetWeb test server: cannot determine port number\n");
   93|      0|		TESTabort();
  ------------------
  |  |   41|      0|	{                                                                          \
  |  |   42|      0|		fprintf(stderr, "!!! Precondition in test environment not met !!!\n"); \
  |  |   43|      0|		fprintf(stderr, "!!! aborting fuzz test in line %u !!!", __LINE__);    \
  |  |   44|      0|		abort();                                                               \
  |  |   45|      0|	}
  ------------------
   94|      0|	}
   95|      1|	if (ports[0].is_ssl != 0) {
  ------------------
  |  Branch (95:6): [True: 0, False: 1]
  ------------------
   96|      0|		fprintf(stderr,
   97|      0|		        "\nCivetWeb fuzz test works on HTTP, not HTTPS.\n"
   98|      0|		        "TLS library should be fuzzed separately.\n");
   99|      0|		TESTabort();
  ------------------
  |  |   41|      0|	{                                                                          \
  |  |   42|      0|		fprintf(stderr, "!!! Precondition in test environment not met !!!\n"); \
  |  |   43|      0|		fprintf(stderr, "!!! aborting fuzz test in line %u !!!", __LINE__);    \
  |  |   44|      0|		abort();                                                               \
  |  |   45|      0|	}
  ------------------
  100|      0|	}
  101|      1|	PORT_NUM_HTTP = ports[0].port;
  102|       |
  103|      1|	printf("CivetWeb server running on port %i\n", (int)PORT_NUM_HTTP);
  104|       |
  105|       |	/* Give server 5 seconds to start, before flooding with requests.
  106|       |	 * Don't know if this is required for fuzz-tests, but it was helpful
  107|       |	 * when testing starting/stopping the server multiple times in test
  108|       |	 * container environments. */
  109|      1|	test_sleep(5);
  ------------------
  |  |   23|      1|#define test_sleep(x) (sleep(x))
  ------------------
  110|      1|	atexit(civetweb_exit);
  111|      1|}
fuzzmain.c:civetweb_exit:
   66|      1|{
   67|      1|	printf("CivetWeb server exit\n");
   68|      1|	mg_stop(ctx);
   69|      1|	ctx = 0;
   70|      1|	test_sleep(5);
  ------------------
  |  |   23|      1|#define test_sleep(x) (sleep(x))
  ------------------
   71|      1|}

mg_get_server_ports:
 3251|      1|{
 3252|      1|	int i, cnt = 0;
 3253|       |
 3254|      1|	if (size <= 0) {
  ------------------
  |  Branch (3254:6): [True: 0, False: 1]
  ------------------
 3255|      0|		return -1;
 3256|      0|	}
 3257|      1|	memset(ports, 0, sizeof(*ports) * (size_t)size);
 3258|      1|	if (!ctx) {
  ------------------
  |  Branch (3258:6): [True: 0, False: 1]
  ------------------
 3259|      0|		return -1;
 3260|      0|	}
 3261|      1|	if (!ctx->listening_sockets) {
  ------------------
  |  Branch (3261:6): [True: 0, False: 1]
  ------------------
 3262|      0|		return -1;
 3263|      0|	}
 3264|       |
 3265|      2|	for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
  ------------------
  |  Branch (3265:14): [True: 2, False: 0]
  |  Branch (3265:28): [True: 1, False: 1]
  ------------------
 3266|       |
 3267|      1|		ports[cnt].port =
 3268|      1|		    ntohs(USA_IN_PORT_UNSAFE(&(ctx->listening_sockets[i].lsa)));
 3269|      1|		ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
 3270|      1|		ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
 3271|       |
 3272|      1|		if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
  ------------------
  |  Branch (3272:7): [True: 1, False: 0]
  ------------------
 3273|       |			/* IPv4 */
 3274|      1|			ports[cnt].protocol = 1;
 3275|      1|			cnt++;
 3276|      1|		} else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
  ------------------
  |  Branch (3276:14): [True: 0, False: 0]
  ------------------
 3277|       |			/* IPv6 */
 3278|      0|			ports[cnt].protocol = 3;
 3279|      0|			cnt++;
 3280|      0|		}
 3281|      1|	}
 3282|       |
 3283|      1|	return cnt;
 3284|      1|}
mg_stop:
20338|      1|{
20339|      1|	pthread_t mt;
20340|      1|	if (!ctx) {
  ------------------
  |  Branch (20340:6): [True: 0, False: 1]
  ------------------
20341|      0|		return;
20342|      0|	}
20343|       |
20344|       |	/* We don't use a lock here. Calling mg_stop with the same ctx from
20345|       |	 * two threads is not allowed. */
20346|      1|	mt = ctx->masterthreadid;
20347|      1|	if (mt == 0) {
  ------------------
  |  Branch (20347:6): [True: 0, False: 1]
  ------------------
20348|      0|		return;
20349|      0|	}
20350|       |
20351|      1|	ctx->masterthreadid = 0;
20352|       |
20353|       |	/* Set stop flag, so all threads know they have to exit. */
20354|      1|	STOP_FLAG_ASSIGN(&ctx->stop_flag, 1);
  ------------------
  |  | 2324|      1|#define STOP_FLAG_ASSIGN(f, v) ((*(f)) = (v))
  ------------------
20355|       |
20356|       |	/* Join timer thread */
20357|       |#if defined(USE_TIMERS)
20358|       |	timers_exit(ctx);
20359|       |#endif
20360|       |
20361|       |	/* Wait until everything has stopped. */
20362|    100|	while (!STOP_FLAG_IS_TWO(&ctx->stop_flag)) {
  ------------------
  |  | 2323|    100|#define STOP_FLAG_IS_TWO(f) ((*(f)) == 2)
  ------------------
  |  Branch (20362:9): [True: 99, False: 1]
  ------------------
20363|     99|		(void)mg_sleep(10);
  ------------------
  |  |  920|     99|#define mg_sleep(x) (usleep((x)*1000))
  ------------------
20364|     99|	}
20365|       |
20366|       |	/* Wait to stop master thread */
20367|      1|	mg_join_thread(mt);
20368|       |
20369|       |	/* Close remaining Lua states */
20370|       |#if defined(USE_LUA)
20371|       |	lua_ctx_exit(ctx);
20372|       |#endif
20373|       |
20374|       |	/* Free memory */
20375|      1|	free_context(ctx);
20376|      1|}
mg_start2:
20456|      1|{
20457|      1|	struct mg_context *ctx;
20458|      1|	const char *name, *value, *default_value;
20459|      1|	int idx, ok, workerthreadcount;
20460|      1|	unsigned int i;
20461|      1|	int itmp;
20462|      1|	void (*exit_callback)(const struct mg_context *ctx) = 0;
20463|      1|	const char **options =
20464|      1|	    ((init != NULL) ? (init->configuration_options) : (NULL));
  ------------------
  |  Branch (20464:7): [True: 1, False: 0]
  ------------------
20465|       |
20466|      1|	struct mg_workerTLS tls;
20467|       |
20468|      1|	if (error != NULL) {
  ------------------
  |  Branch (20468:6): [True: 0, False: 1]
  ------------------
20469|      0|		error->code = MG_ERROR_DATA_CODE_OK;
20470|      0|		error->code_sub = 0;
20471|      0|		if (error->text_buffer_size > 0) {
  ------------------
  |  Branch (20471:7): [True: 0, False: 0]
  ------------------
20472|      0|			*error->text = 0;
20473|      0|		}
20474|      0|	}
20475|       |
20476|      1|	if (mg_init_library_called == 0) {
  ------------------
  |  Branch (20476:6): [True: 1, False: 0]
  ------------------
20477|       |		/* Legacy INIT, if mg_start is called without mg_init_library.
20478|       |		 * Note: This will cause a memory leak when unloading the library.
20479|       |		 */
20480|      1|		legacy_init(options);
20481|      1|	}
20482|      1|	if (mg_init_library_called == 0) {
  ------------------
  |  Branch (20482:6): [True: 0, False: 1]
  ------------------
20483|      0|		if (error != NULL) {
  ------------------
  |  Branch (20483:7): [True: 0, False: 0]
  ------------------
20484|      0|			error->code = MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED;
20485|      0|			mg_snprintf(NULL,
20486|      0|			            NULL, /* No truncation check for error buffers */
20487|      0|			            error->text,
20488|      0|			            error->text_buffer_size,
20489|      0|			            "%s",
20490|      0|			            "Library uninitialized");
20491|      0|		}
20492|      0|		return NULL;
20493|      0|	}
20494|       |
20495|       |	/* Allocate context and initialize reasonable general case defaults. */
20496|      1|	ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx));
20497|      1|	if (ctx == NULL) {
  ------------------
  |  Branch (20497:6): [True: 0, False: 1]
  ------------------
20498|      0|		if (error != NULL) {
  ------------------
  |  Branch (20498:7): [True: 0, False: 0]
  ------------------
20499|      0|			error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
20500|      0|			error->code_sub = (unsigned)sizeof(*ctx);
20501|      0|			mg_snprintf(NULL,
20502|      0|			            NULL, /* No truncation check for error buffers */
20503|      0|			            error->text,
20504|      0|			            error->text_buffer_size,
20505|      0|			            "%s",
20506|      0|			            "Out of memory");
20507|      0|		}
20508|      0|		return NULL;
20509|      0|	}
20510|       |
20511|       |	/* Random number generator will initialize at the first call */
20512|      1|	ctx->dd.auth_nonce_mask =
20513|      1|	    (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
20514|       |
20515|       |	/* Save started thread index to reuse in other external API calls
20516|       |	 * For the sake of thread synchronization all non-civetweb threads
20517|       |	 * can be considered as single external thread */
20518|      1|	ctx->starter_thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
20519|      1|	tls.is_master = -1; /* Thread calling mg_start */
20520|      1|	tls.thread_idx = ctx->starter_thread_idx;
20521|       |#if defined(_WIN32)
20522|       |	tls.pthread_cond_helper_mutex = NULL;
20523|       |#endif
20524|      1|	pthread_setspecific(sTlsKey, &tls);
20525|       |
20526|      1|	ok = (0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr));
20527|      1|#if !defined(ALTERNATIVE_QUEUE)
20528|      1|	ok &= (0 == pthread_cond_init(&ctx->sq_empty, NULL));
20529|      1|	ok &= (0 == pthread_cond_init(&ctx->sq_full, NULL));
20530|      1|	ctx->sq_blocked = 0;
20531|      1|#endif
20532|      1|	ok &= (0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr));
20533|       |#if defined(USE_LUA)
20534|       |	ok &= (0 == pthread_mutex_init(&ctx->lua_bg_mutex, &pthread_mutex_attr));
20535|       |#endif
20536|      1|	if (!ok) {
  ------------------
  |  Branch (20536:6): [True: 0, False: 1]
  ------------------
20537|      0|		unsigned error_id = (unsigned)ERRNO;
  ------------------
  |  |  924|      0|#define ERRNO (errno)
  ------------------
20538|      0|		const char *err_msg =
20539|      0|		    "Cannot initialize thread synchronization objects";
20540|       |		/* Fatal error - abort start. However, this situation should never
20541|       |		 * occur in practice. */
20542|       |
20543|      0|		mg_cry_ctx_internal(ctx, "%s", err_msg);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20544|      0|		if (error != NULL) {
  ------------------
  |  Branch (20544:7): [True: 0, False: 0]
  ------------------
20545|      0|			error->code = MG_ERROR_DATA_CODE_OS_ERROR;
20546|      0|			error->code_sub = error_id;
20547|      0|			mg_snprintf(NULL,
20548|      0|			            NULL, /* No truncation check for error buffers */
20549|      0|			            error->text,
20550|      0|			            error->text_buffer_size,
20551|      0|			            "%s",
20552|      0|			            err_msg);
20553|      0|		}
20554|       |
20555|      0|		mg_free(ctx);
20556|      0|		pthread_setspecific(sTlsKey, NULL);
20557|      0|		return NULL;
20558|      0|	}
20559|       |
20560|      1|	if ((init != NULL) && (init->callbacks != NULL)) {
  ------------------
  |  Branch (20560:6): [True: 1, False: 0]
  |  Branch (20560:24): [True: 1, False: 0]
  ------------------
20561|       |		/* Set all callbacks except exit_context. */
20562|      1|		ctx->callbacks = *init->callbacks;
20563|      1|		exit_callback = init->callbacks->exit_context;
20564|       |		/* The exit callback is activated once the context is successfully
20565|       |		 * created. It should not be called, if an incomplete context object
20566|       |		 * is deleted during a failed initialization. */
20567|      1|		ctx->callbacks.exit_context = 0;
20568|      1|	}
20569|      1|	ctx->user_data = ((init != NULL) ? (init->user_data) : (NULL));
  ------------------
  |  Branch (20569:20): [True: 1, False: 0]
  ------------------
20570|      1|	ctx->dd.handlers = NULL;
20571|      1|	ctx->dd.next = NULL;
20572|       |
20573|       |#if defined(USE_LUA)
20574|       |	lua_ctx_init(ctx);
20575|       |#endif
20576|       |
20577|       |	/* Store options */
20578|      3|	while (options && (name = *options++) != NULL) {
  ------------------
  |  Branch (20578:9): [True: 3, False: 0]
  |  Branch (20578:20): [True: 2, False: 1]
  ------------------
20579|      2|		idx = get_option_index(name);
20580|      2|		if (idx == -1) {
  ------------------
  |  Branch (20580:7): [True: 0, False: 2]
  ------------------
20581|      0|			mg_cry_ctx_internal(ctx, "Invalid option: %s", name);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20582|      0|			if (error != NULL) {
  ------------------
  |  Branch (20582:8): [True: 0, False: 0]
  ------------------
20583|      0|				error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
20584|      0|				error->code_sub = (unsigned)-1;
20585|      0|				mg_snprintf(NULL,
20586|      0|				            NULL, /* No truncation check for error buffers */
20587|      0|				            error->text,
20588|      0|				            error->text_buffer_size,
20589|      0|				            "Invalid configuration option: %s",
20590|      0|				            name);
20591|      0|			}
20592|       |
20593|      0|			free_context(ctx);
20594|      0|			pthread_setspecific(sTlsKey, NULL);
20595|      0|			return NULL;
20596|       |
20597|      2|		} else if ((value = *options++) == NULL) {
  ------------------
  |  Branch (20597:14): [True: 0, False: 2]
  ------------------
20598|      0|			mg_cry_ctx_internal(ctx, "%s: option value cannot be NULL", name);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20599|      0|			if (error != NULL) {
  ------------------
  |  Branch (20599:8): [True: 0, False: 0]
  ------------------
20600|      0|				error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
20601|      0|				error->code_sub = (unsigned)idx;
20602|      0|				mg_snprintf(NULL,
20603|      0|				            NULL, /* No truncation check for error buffers */
20604|      0|				            error->text,
20605|      0|				            error->text_buffer_size,
20606|      0|				            "Invalid configuration option value: %s",
20607|      0|				            name);
20608|      0|			}
20609|       |
20610|      0|			free_context(ctx);
20611|      0|			pthread_setspecific(sTlsKey, NULL);
20612|      0|			return NULL;
20613|      0|		}
20614|      2|		if (ctx->dd.config[idx] != NULL) {
  ------------------
  |  Branch (20614:7): [True: 0, False: 2]
  ------------------
20615|       |			/* A duplicate configuration option is not an error - the last
20616|       |			 * option value will be used. */
20617|      0|			mg_cry_ctx_internal(ctx, "warning: %s: duplicate option", name);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20618|      0|			mg_free(ctx->dd.config[idx]);
20619|      0|		}
20620|      2|		ctx->dd.config[idx] = mg_strdup_ctx(value, ctx);
20621|      2|		DEBUG_TRACE("[%s] -> [%s]", name, value);
  ------------------
  |  |  243|      2|	do {                                                                       \
  |  |  244|      2|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
20622|      2|	}
20623|       |
20624|       |	/* Set default value if needed */
20625|     62|	for (i = 0; config_options[i].name != NULL; i++) {
  ------------------
  |  Branch (20625:14): [True: 61, False: 1]
  ------------------
20626|     61|		default_value = config_options[i].default_value;
20627|     61|		if ((ctx->dd.config[i] == NULL) && (default_value != NULL)) {
  ------------------
  |  Branch (20627:7): [True: 59, False: 2]
  |  Branch (20627:38): [True: 31, False: 28]
  ------------------
20628|     31|			ctx->dd.config[i] = mg_strdup_ctx(default_value, ctx);
20629|     31|		}
20630|     61|	}
20631|       |
20632|       |	/* Request size option */
20633|      1|	itmp = atoi(ctx->dd.config[MAX_REQUEST_SIZE]);
20634|      1|	if (itmp < 1024) {
  ------------------
  |  Branch (20634:6): [True: 0, False: 1]
  ------------------
20635|      0|		mg_cry_ctx_internal(ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20636|      0|		                    "%s too small",
20637|      0|		                    config_options[MAX_REQUEST_SIZE].name);
20638|      0|		if (error != NULL) {
  ------------------
  |  Branch (20638:7): [True: 0, False: 0]
  ------------------
20639|      0|			error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
20640|      0|			error->code_sub = (unsigned)MAX_REQUEST_SIZE;
20641|      0|			mg_snprintf(NULL,
20642|      0|			            NULL, /* No truncation check for error buffers */
20643|      0|			            error->text,
20644|      0|			            error->text_buffer_size,
20645|      0|			            "Invalid configuration option value: %s",
20646|      0|			            config_options[MAX_REQUEST_SIZE].name);
20647|      0|		}
20648|       |
20649|      0|		free_context(ctx);
20650|      0|		pthread_setspecific(sTlsKey, NULL);
20651|      0|		return NULL;
20652|      0|	}
20653|      1|	ctx->max_request_size = (unsigned)itmp;
20654|       |
20655|       |	/* Queue length */
20656|      1|#if !defined(ALTERNATIVE_QUEUE)
20657|      1|	itmp = atoi(ctx->dd.config[CONNECTION_QUEUE_SIZE]);
20658|      1|	if (itmp < 1) {
  ------------------
  |  Branch (20658:6): [True: 0, False: 1]
  ------------------
20659|      0|		mg_cry_ctx_internal(ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20660|      0|		                    "%s too small",
20661|      0|		                    config_options[CONNECTION_QUEUE_SIZE].name);
20662|      0|		if (error != NULL) {
  ------------------
  |  Branch (20662:7): [True: 0, False: 0]
  ------------------
20663|      0|			error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
20664|      0|			error->code_sub = CONNECTION_QUEUE_SIZE;
20665|      0|			mg_snprintf(NULL,
20666|      0|			            NULL, /* No truncation check for error buffers */
20667|      0|			            error->text,
20668|      0|			            error->text_buffer_size,
20669|      0|			            "Invalid configuration option value: %s",
20670|      0|			            config_options[CONNECTION_QUEUE_SIZE].name);
20671|      0|		}
20672|       |
20673|      0|		free_context(ctx);
20674|      0|		pthread_setspecific(sTlsKey, NULL);
20675|      0|		return NULL;
20676|      0|	}
20677|      1|	ctx->squeue =
20678|      1|	    (struct socket *)mg_calloc((unsigned int)itmp, sizeof(struct socket));
20679|      1|	if (ctx->squeue == NULL) {
  ------------------
  |  Branch (20679:6): [True: 0, False: 1]
  ------------------
20680|      0|		mg_cry_ctx_internal(ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20681|      0|		                    "Out of memory: Cannot allocate %s",
20682|      0|		                    config_options[CONNECTION_QUEUE_SIZE].name);
20683|      0|		if (error != NULL) {
  ------------------
  |  Branch (20683:7): [True: 0, False: 0]
  ------------------
20684|      0|			error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
20685|      0|			error->code_sub = (unsigned)itmp * (unsigned)sizeof(struct socket);
20686|      0|			mg_snprintf(NULL,
20687|      0|			            NULL, /* No truncation check for error buffers */
20688|      0|			            error->text,
20689|      0|			            error->text_buffer_size,
20690|      0|			            "Out of memory: Cannot allocate %s",
20691|      0|			            config_options[CONNECTION_QUEUE_SIZE].name);
20692|      0|		}
20693|       |
20694|      0|		free_context(ctx);
20695|      0|		pthread_setspecific(sTlsKey, NULL);
20696|      0|		return NULL;
20697|      0|	}
20698|      1|	ctx->sq_size = itmp;
20699|      1|#endif
20700|       |
20701|       |	/* Worker thread count option */
20702|      1|	workerthreadcount = atoi(ctx->dd.config[NUM_THREADS]);
20703|       |
20704|      1|	if ((workerthreadcount > MAX_WORKER_THREADS) || (workerthreadcount <= 0)) {
  ------------------
  |  |  465|      1|#define MAX_WORKER_THREADS (1024 * 64) /* in threads (count) */
  ------------------
  |  Branch (20704:6): [True: 0, False: 1]
  |  Branch (20704:50): [True: 0, False: 1]
  ------------------
20705|      0|		if (workerthreadcount <= 0) {
  ------------------
  |  Branch (20705:7): [True: 0, False: 0]
  ------------------
20706|      0|			mg_cry_ctx_internal(ctx, "%s", "Invalid number of worker threads");
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20707|      0|		} else {
20708|      0|			mg_cry_ctx_internal(ctx, "%s", "Too many worker threads");
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20709|      0|		}
20710|      0|		if (error != NULL) {
  ------------------
  |  Branch (20710:7): [True: 0, False: 0]
  ------------------
20711|      0|			error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
20712|      0|			error->code_sub = NUM_THREADS;
20713|      0|			mg_snprintf(NULL,
20714|      0|			            NULL, /* No truncation check for error buffers */
20715|      0|			            error->text,
20716|      0|			            error->text_buffer_size,
20717|      0|			            "Invalid configuration option value: %s",
20718|      0|			            config_options[NUM_THREADS].name);
20719|      0|		}
20720|       |
20721|      0|		free_context(ctx);
20722|      0|		pthread_setspecific(sTlsKey, NULL);
20723|      0|		return NULL;
20724|      0|	}
20725|       |
20726|       |	/* Document root */
20727|       |#if defined(NO_FILES)
20728|       |	if (ctx->dd.config[DOCUMENT_ROOT] != NULL) {
20729|       |		mg_cry_ctx_internal(ctx, "%s", "Document root must not be set");
20730|       |		if (error != NULL) {
20731|       |			error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
20732|       |			error->code_sub = (unsigned)DOCUMENT_ROOT;
20733|       |			mg_snprintf(NULL,
20734|       |			            NULL, /* No truncation check for error buffers */
20735|       |			            error->text,
20736|       |			            error->text_buffer_size,
20737|       |			            "Invalid configuration option value: %s",
20738|       |			            config_options[DOCUMENT_ROOT].name);
20739|       |		}
20740|       |
20741|       |		free_context(ctx);
20742|       |		pthread_setspecific(sTlsKey, NULL);
20743|       |		return NULL;
20744|       |	}
20745|       |#endif
20746|       |
20747|      1|	get_system_name(&ctx->systemName);
20748|       |
20749|       |#if defined(USE_LUA)
20750|       |	/* If a Lua background script has been configured, start it. */
20751|       |	ctx->lua_bg_log_available = 0;
20752|       |	if (ctx->dd.config[LUA_BACKGROUND_SCRIPT] != NULL) {
20753|       |		char ebuf[256];
20754|       |		struct vec opt_vec;
20755|       |		struct vec eq_vec;
20756|       |		const char *sparams;
20757|       |
20758|       |		memset(ebuf, 0, sizeof(ebuf));
20759|       |		pthread_mutex_lock(&ctx->lua_bg_mutex);
20760|       |
20761|       |		/* Create a Lua state, load all standard libraries and the mg table */
20762|       |		lua_State *state = mg_lua_context_script_prepare(
20763|       |		    ctx->dd.config[LUA_BACKGROUND_SCRIPT], ctx, ebuf, sizeof(ebuf));
20764|       |		if (!state) {
20765|       |			mg_cry_ctx_internal(ctx,
20766|       |			                    "lua_background_script load error: %s",
20767|       |			                    ebuf);
20768|       |			if (error != NULL) {
20769|       |				error->code = MG_ERROR_DATA_CODE_SCRIPT_ERROR;
20770|       |				mg_snprintf(NULL,
20771|       |				            NULL, /* No truncation check for error buffers */
20772|       |				            error->text,
20773|       |				            error->text_buffer_size,
20774|       |				            "Error in script %s: %s",
20775|       |				            config_options[LUA_BACKGROUND_SCRIPT].name,
20776|       |				            ebuf);
20777|       |			}
20778|       |
20779|       |			pthread_mutex_unlock(&ctx->lua_bg_mutex);
20780|       |
20781|       |			free_context(ctx);
20782|       |			pthread_setspecific(sTlsKey, NULL);
20783|       |			return NULL;
20784|       |		}
20785|       |
20786|       |		/* Add a table with parameters into mg.params */
20787|       |		sparams = ctx->dd.config[LUA_BACKGROUND_SCRIPT_PARAMS];
20788|       |		if (sparams && sparams[0]) {
20789|       |			lua_getglobal(state, "mg");
20790|       |			lua_pushstring(state, "params");
20791|       |			lua_newtable(state);
20792|       |
20793|       |			while ((sparams = next_option(sparams, &opt_vec, &eq_vec))
20794|       |			       != NULL) {
20795|       |				reg_llstring(
20796|       |				    state, opt_vec.ptr, opt_vec.len, eq_vec.ptr, eq_vec.len);
20797|       |				if (mg_strncasecmp(sparams, opt_vec.ptr, opt_vec.len) == 0)
20798|       |					break;
20799|       |			}
20800|       |			lua_rawset(state, -3);
20801|       |			lua_pop(state, 1);
20802|       |		}
20803|       |
20804|       |		/* Call script */
20805|       |		state = mg_lua_context_script_run(state,
20806|       |		                                  ctx->dd.config[LUA_BACKGROUND_SCRIPT],
20807|       |		                                  ctx,
20808|       |		                                  ebuf,
20809|       |		                                  sizeof(ebuf));
20810|       |		if (!state) {
20811|       |			mg_cry_ctx_internal(ctx,
20812|       |			                    "lua_background_script start error: %s",
20813|       |			                    ebuf);
20814|       |			if (error != NULL) {
20815|       |				error->code = MG_ERROR_DATA_CODE_SCRIPT_ERROR;
20816|       |				mg_snprintf(NULL,
20817|       |				            NULL, /* No truncation check for error buffers */
20818|       |				            error->text,
20819|       |				            error->text_buffer_size,
20820|       |				            "Error in script %s: %s",
20821|       |				            config_options[DOCUMENT_ROOT].name,
20822|       |				            ebuf);
20823|       |			}
20824|       |			pthread_mutex_unlock(&ctx->lua_bg_mutex);
20825|       |
20826|       |			free_context(ctx);
20827|       |			pthread_setspecific(sTlsKey, NULL);
20828|       |			return NULL;
20829|       |		}
20830|       |
20831|       |		/* state remains valid */
20832|       |		ctx->lua_background_state = (void *)state;
20833|       |		pthread_mutex_unlock(&ctx->lua_bg_mutex);
20834|       |
20835|       |	} else {
20836|       |		ctx->lua_background_state = 0;
20837|       |	}
20838|       |#endif
20839|       |
20840|       |	/* Step by step initialization of ctx - depending on build options */
20841|      1|#if !defined(NO_FILESYSTEMS)
20842|      1|	if (!set_gpass_option(ctx, NULL)) {
  ------------------
  |  Branch (20842:6): [True: 0, False: 1]
  ------------------
20843|      0|		const char *err_msg = "Invalid global password file";
20844|       |		/* Fatal error - abort start. */
20845|      0|		mg_cry_ctx_internal(ctx, "%s", err_msg);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20846|       |
20847|      0|		if (error != NULL) {
  ------------------
  |  Branch (20847:7): [True: 0, False: 0]
  ------------------
20848|      0|			error->code = MG_ERROR_DATA_CODE_INVALID_PASS_FILE;
20849|      0|			mg_snprintf(NULL,
20850|      0|			            NULL, /* No truncation check for error buffers */
20851|      0|			            error->text,
20852|      0|			            error->text_buffer_size,
20853|      0|			            "%s",
20854|      0|			            err_msg);
20855|      0|		}
20856|      0|		free_context(ctx);
20857|      0|		pthread_setspecific(sTlsKey, NULL);
20858|      0|		return NULL;
20859|      0|	}
20860|      1|#endif
20861|       |
20862|       |#if defined(USE_MBEDTLS)
20863|       |	if (!mg_sslctx_init(ctx, NULL)) {
20864|       |		const char *err_msg = "Error initializing SSL context";
20865|       |		/* Fatal error - abort start. */
20866|       |		mg_cry_ctx_internal(ctx, "%s", err_msg);
20867|       |
20868|       |		if (error != NULL) {
20869|       |			error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED;
20870|       |			mg_snprintf(NULL,
20871|       |			            NULL, /* No truncation check for error buffers */
20872|       |			            error->text,
20873|       |			            error->text_buffer_size,
20874|       |			            "%s",
20875|       |			            err_msg);
20876|       |		}
20877|       |
20878|       |		free_context(ctx);
20879|       |		pthread_setspecific(sTlsKey, NULL);
20880|       |		return NULL;
20881|       |	}
20882|       |
20883|       |#elif !defined(NO_SSL)
20884|      1|	if (!init_ssl_ctx(ctx, NULL)) {
  ------------------
  |  Branch (20884:6): [True: 0, False: 1]
  ------------------
20885|      0|		const char *err_msg = "Error initializing SSL context";
20886|       |		/* Fatal error - abort start. */
20887|      0|		mg_cry_ctx_internal(ctx, "%s", err_msg);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20888|       |
20889|      0|		if (error != NULL) {
  ------------------
  |  Branch (20889:7): [True: 0, False: 0]
  ------------------
20890|      0|			error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED;
20891|      0|			mg_snprintf(NULL,
20892|      0|			            NULL, /* No truncation check for error buffers */
20893|      0|			            error->text,
20894|      0|			            error->text_buffer_size,
20895|      0|			            "%s",
20896|      0|			            err_msg);
20897|      0|		}
20898|       |
20899|      0|		free_context(ctx);
20900|      0|		pthread_setspecific(sTlsKey, NULL);
20901|      0|		return NULL;
20902|      0|	}
20903|      1|#endif
20904|       |
20905|      1|	if (!set_ports_option(ctx)) {
  ------------------
  |  Branch (20905:6): [True: 0, False: 1]
  ------------------
20906|      0|		const char *err_msg = "Failed to setup server ports";
20907|       |		/* Fatal error - abort start. */
20908|      0|		mg_cry_ctx_internal(ctx, "%s", err_msg);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20909|       |
20910|      0|		if (error != NULL) {
  ------------------
  |  Branch (20910:7): [True: 0, False: 0]
  ------------------
20911|      0|			error->code = MG_ERROR_DATA_CODE_INIT_PORTS_FAILED;
20912|      0|			mg_snprintf(NULL,
20913|      0|			            NULL, /* No truncation check for error buffers */
20914|      0|			            error->text,
20915|      0|			            error->text_buffer_size,
20916|      0|			            "%s",
20917|      0|			            err_msg);
20918|      0|		}
20919|       |
20920|      0|		free_context(ctx);
20921|      0|		pthread_setspecific(sTlsKey, NULL);
20922|      0|		return NULL;
20923|      0|	}
20924|       |
20925|      1|#if !defined(_WIN32) && !defined(__ZEPHYR__)
20926|      1|	if (!set_uid_option(ctx)) {
  ------------------
  |  Branch (20926:6): [True: 0, False: 1]
  ------------------
20927|      0|		const char *err_msg = "Failed to run as configured user";
20928|       |		/* Fatal error - abort start. */
20929|      0|		mg_cry_ctx_internal(ctx, "%s", err_msg);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20930|       |
20931|      0|		if (error != NULL) {
  ------------------
  |  Branch (20931:7): [True: 0, False: 0]
  ------------------
20932|      0|			error->code = MG_ERROR_DATA_CODE_INIT_USER_FAILED;
20933|      0|			mg_snprintf(NULL,
20934|      0|			            NULL, /* No truncation check for error buffers */
20935|      0|			            error->text,
20936|      0|			            error->text_buffer_size,
20937|      0|			            "%s",
20938|      0|			            err_msg);
20939|      0|		}
20940|       |
20941|      0|		free_context(ctx);
20942|      0|		pthread_setspecific(sTlsKey, NULL);
20943|      0|		return NULL;
20944|      0|	}
20945|      1|#endif
20946|       |
20947|      1|	if (!set_acl_option(ctx)) {
  ------------------
  |  Branch (20947:6): [True: 0, False: 1]
  ------------------
20948|      0|		const char *err_msg = "Failed to setup access control list";
20949|       |		/* Fatal error - abort start. */
20950|      0|		mg_cry_ctx_internal(ctx, "%s", err_msg);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20951|       |
20952|      0|		if (error != NULL) {
  ------------------
  |  Branch (20952:7): [True: 0, False: 0]
  ------------------
20953|      0|			error->code = MG_ERROR_DATA_CODE_INIT_ACL_FAILED;
20954|      0|			mg_snprintf(NULL,
20955|      0|			            NULL, /* No truncation check for error buffers */
20956|      0|			            error->text,
20957|      0|			            error->text_buffer_size,
20958|      0|			            "%s",
20959|      0|			            err_msg);
20960|      0|		}
20961|       |
20962|      0|		free_context(ctx);
20963|      0|		pthread_setspecific(sTlsKey, NULL);
20964|      0|		return NULL;
20965|      0|	}
20966|       |
20967|      1|	ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
20968|      1|	ctx->worker_threadids = (pthread_t *)mg_calloc_ctx(ctx->cfg_worker_threads,
  ------------------
  |  | 1498|      1|#define mg_calloc_ctx(a, b, c) mg_calloc(a, b)
  ------------------
20969|      1|	                                                   sizeof(pthread_t),
20970|      1|	                                                   ctx);
20971|       |
20972|      1|	if (ctx->worker_threadids == NULL) {
  ------------------
  |  Branch (20972:6): [True: 0, False: 1]
  ------------------
20973|      0|		const char *err_msg = "Not enough memory for worker thread ID array";
20974|      0|		mg_cry_ctx_internal(ctx, "%s", err_msg);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
20975|       |
20976|      0|		if (error != NULL) {
  ------------------
  |  Branch (20976:7): [True: 0, False: 0]
  ------------------
20977|      0|			error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
20978|      0|			error->code_sub =
20979|      0|			    (unsigned)ctx->cfg_worker_threads * (unsigned)sizeof(pthread_t);
20980|      0|			mg_snprintf(NULL,
20981|      0|			            NULL, /* No truncation check for error buffers */
20982|      0|			            error->text,
20983|      0|			            error->text_buffer_size,
20984|      0|			            "%s",
20985|      0|			            err_msg);
20986|      0|		}
20987|       |
20988|      0|		free_context(ctx);
20989|      0|		pthread_setspecific(sTlsKey, NULL);
20990|      0|		return NULL;
20991|      0|	}
20992|      1|	ctx->worker_connections =
20993|      1|	    (struct mg_connection *)mg_calloc_ctx(ctx->cfg_worker_threads,
  ------------------
  |  | 1498|      1|#define mg_calloc_ctx(a, b, c) mg_calloc(a, b)
  ------------------
20994|      1|	                                          sizeof(struct mg_connection),
20995|      1|	                                          ctx);
20996|      1|	if (ctx->worker_connections == NULL) {
  ------------------
  |  Branch (20996:6): [True: 0, False: 1]
  ------------------
20997|      0|		const char *err_msg =
20998|      0|		    "Not enough memory for worker thread connection array";
20999|      0|		mg_cry_ctx_internal(ctx, "%s", err_msg);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
21000|       |
21001|      0|		if (error != NULL) {
  ------------------
  |  Branch (21001:7): [True: 0, False: 0]
  ------------------
21002|      0|			error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
21003|      0|			error->code_sub = (unsigned)ctx->cfg_worker_threads
21004|      0|			                  * (unsigned)sizeof(struct mg_connection);
21005|      0|			mg_snprintf(NULL,
21006|      0|			            NULL, /* No truncation check for error buffers */
21007|      0|			            error->text,
21008|      0|			            error->text_buffer_size,
21009|      0|			            "%s",
21010|      0|			            err_msg);
21011|      0|		}
21012|       |
21013|      0|		free_context(ctx);
21014|      0|		pthread_setspecific(sTlsKey, NULL);
21015|      0|		return NULL;
21016|      0|	}
21017|       |
21018|       |#if defined(ALTERNATIVE_QUEUE)
21019|       |	ctx->client_wait_events =
21020|       |	    (void **)mg_calloc_ctx(ctx->cfg_worker_threads,
21021|       |	                           sizeof(ctx->client_wait_events[0]),
21022|       |	                           ctx);
21023|       |	if (ctx->client_wait_events == NULL) {
21024|       |		const char *err_msg = "Not enough memory for worker event array";
21025|       |		mg_cry_ctx_internal(ctx, "%s", err_msg);
21026|       |		mg_free(ctx->worker_threadids);
21027|       |
21028|       |		if (error != NULL) {
21029|       |			error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
21030|       |			error->code_sub = (unsigned)ctx->cfg_worker_threads
21031|       |			                  * (unsigned)sizeof(ctx->client_wait_events[0]);
21032|       |			mg_snprintf(NULL,
21033|       |			            NULL, /* No truncation check for error buffers */
21034|       |			            error->text,
21035|       |			            error->text_buffer_size,
21036|       |			            "%s",
21037|       |			            err_msg);
21038|       |		}
21039|       |
21040|       |		free_context(ctx);
21041|       |		pthread_setspecific(sTlsKey, NULL);
21042|       |		return NULL;
21043|       |	}
21044|       |
21045|       |	ctx->client_socks =
21046|       |	    (struct socket *)mg_calloc_ctx(ctx->cfg_worker_threads,
21047|       |	                                   sizeof(ctx->client_socks[0]),
21048|       |	                                   ctx);
21049|       |	if (ctx->client_socks == NULL) {
21050|       |		const char *err_msg = "Not enough memory for worker socket array";
21051|       |		mg_cry_ctx_internal(ctx, "%s", err_msg);
21052|       |		mg_free(ctx->client_wait_events);
21053|       |		mg_free(ctx->worker_threadids);
21054|       |
21055|       |		if (error != NULL) {
21056|       |			error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
21057|       |			error->code_sub = (unsigned)ctx->cfg_worker_threads
21058|       |			                  * (unsigned)sizeof(ctx->client_socks[0]);
21059|       |			mg_snprintf(NULL,
21060|       |			            NULL, /* No truncation check for error buffers */
21061|       |			            error->text,
21062|       |			            error->text_buffer_size,
21063|       |			            "%s",
21064|       |			            err_msg);
21065|       |		}
21066|       |
21067|       |		free_context(ctx);
21068|       |		pthread_setspecific(sTlsKey, NULL);
21069|       |		return NULL;
21070|       |	}
21071|       |
21072|       |	for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
21073|       |		ctx->client_wait_events[i] = event_create();
21074|       |		if (ctx->client_wait_events[i] == 0) {
21075|       |			const char *err_msg = "Error creating worker event %i";
21076|       |			mg_cry_ctx_internal(ctx, err_msg, i);
21077|       |			while (i > 0) {
21078|       |				i--;
21079|       |				event_destroy(ctx->client_wait_events[i]);
21080|       |			}
21081|       |			mg_free(ctx->client_socks);
21082|       |			mg_free(ctx->client_wait_events);
21083|       |			mg_free(ctx->worker_threadids);
21084|       |
21085|       |			if (error != NULL) {
21086|       |				error->code = MG_ERROR_DATA_CODE_OS_ERROR;
21087|       |				error->code_sub = ERRNO;
21088|       |				mg_snprintf(NULL,
21089|       |				            NULL, /* No truncation check for error buffers */
21090|       |				            error->text,
21091|       |				            error->text_buffer_size,
21092|       |				            err_msg,
21093|       |				            i);
21094|       |			}
21095|       |
21096|       |			free_context(ctx);
21097|       |			pthread_setspecific(sTlsKey, NULL);
21098|       |			return NULL;
21099|       |		}
21100|       |	}
21101|       |#endif
21102|       |
21103|       |#if defined(USE_TIMERS)
21104|       |	if (timers_init(ctx) != 0) {
21105|       |		const char *err_msg = "Error creating timers";
21106|       |		mg_cry_ctx_internal(ctx, "%s", err_msg);
21107|       |
21108|       |		if (error != NULL) {
21109|       |			error->code = MG_ERROR_DATA_CODE_OS_ERROR;
21110|       |			error->code_sub = ERRNO;
21111|       |			mg_snprintf(NULL,
21112|       |			            NULL, /* No truncation check for error buffers */
21113|       |			            error->text,
21114|       |			            error->text_buffer_size,
21115|       |			            "%s",
21116|       |			            err_msg);
21117|       |		}
21118|       |
21119|       |		free_context(ctx);
21120|       |		pthread_setspecific(sTlsKey, NULL);
21121|       |		return NULL;
21122|       |	}
21123|       |#endif
21124|       |
21125|       |	/* Context has been created - init user libraries */
21126|      1|	if (ctx->callbacks.init_context) {
  ------------------
  |  Branch (21126:6): [True: 0, False: 1]
  ------------------
21127|      0|		ctx->callbacks.init_context(ctx);
21128|      0|	}
21129|       |
21130|       |	/* From now, the context is successfully created.
21131|       |	 * When it is destroyed, the exit callback should be called. */
21132|      1|	ctx->callbacks.exit_context = exit_callback;
21133|      1|	ctx->context_type = CONTEXT_SERVER; /* server context */
21134|       |
21135|       |	/* Start worker threads */
21136|     51|	for (i = 0; i < ctx->cfg_worker_threads; i++) {
  ------------------
  |  Branch (21136:14): [True: 50, False: 1]
  ------------------
21137|       |		/* worker_thread sets up the other fields */
21138|     50|		ctx->worker_connections[i].phys_ctx = ctx;
21139|     50|		if (mg_start_thread_with_id(worker_thread,
  ------------------
  |  Branch (21139:7): [True: 0, False: 50]
  ------------------
21140|     50|		                            &ctx->worker_connections[i],
21141|     50|		                            &ctx->worker_threadids[i])
21142|     50|		    != 0) {
21143|       |
21144|      0|			long error_no = (long)ERRNO;
  ------------------
  |  |  924|      0|#define ERRNO (errno)
  ------------------
21145|       |
21146|       |			/* thread was not created */
21147|      0|			if (i > 0) {
  ------------------
  |  Branch (21147:8): [True: 0, False: 0]
  ------------------
21148|       |				/* If the second, third, ... thread cannot be created, set a
21149|       |				 * warning, but keep running. */
21150|      0|				mg_cry_ctx_internal(ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
21151|      0|				                    "Cannot start worker thread %i: error %ld",
21152|      0|				                    i + 1,
21153|      0|				                    error_no);
21154|       |
21155|       |				/* If the server initialization should stop here, all
21156|       |				 * threads that have already been created must be stopped
21157|       |				 * first, before any free_context(ctx) call.
21158|       |				 */
21159|       |
21160|      0|			} else {
21161|       |				/* If the first worker thread cannot be created, stop
21162|       |				 * initialization and free the entire server context. */
21163|      0|				mg_cry_ctx_internal(ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
21164|      0|				                    "Cannot create threads: error %ld",
21165|      0|				                    error_no);
21166|       |
21167|      0|				if (error != NULL) {
  ------------------
  |  Branch (21167:9): [True: 0, False: 0]
  ------------------
21168|      0|					error->code = MG_ERROR_DATA_CODE_OS_ERROR;
21169|      0|					error->code_sub = (unsigned)error_no;
21170|      0|					mg_snprintf(
21171|      0|					    NULL,
21172|      0|					    NULL, /* No truncation check for error buffers */
21173|      0|					    error->text,
21174|      0|					    error->text_buffer_size,
21175|      0|					    "Cannot create first worker thread: error %ld",
21176|      0|					    error_no);
21177|      0|				}
21178|       |
21179|      0|				free_context(ctx);
21180|      0|				pthread_setspecific(sTlsKey, NULL);
21181|      0|				return NULL;
21182|      0|			}
21183|      0|			break;
21184|      0|		}
21185|     50|	}
21186|       |
21187|       |	/* Start master (listening) thread */
21188|      1|	mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
21189|       |
21190|      1|	pthread_setspecific(sTlsKey, NULL);
21191|      1|	return ctx;
21192|      1|}
mg_start:
21199|      1|{
21200|      1|	struct mg_init_data init = {0};
21201|      1|	init.callbacks = callbacks;
21202|      1|	init.user_data = user_data;
21203|      1|	init.configuration_options = options;
21204|       |
21205|      1|	return mg_start2(&init, NULL);
21206|      1|}
mg_check_feature:
21422|      1|{
21423|      1|	static const unsigned feature_set = 0
21424|       |	/* Set bits for available features according to API documentation.
21425|       |	 * This bit mask is created at compile time, according to the active
21426|       |	 * preprocessor defines. It is a single const value at runtime. */
21427|      1|#if !defined(NO_FILES)
21428|      1|	                                    | MG_FEATURES_FILES
21429|      1|#endif
21430|      1|#if !defined(NO_SSL) || defined(USE_MBEDTLS)
21431|      1|	                                    | MG_FEATURES_SSL
21432|      1|#endif
21433|      1|#if !defined(NO_CGI)
21434|      1|	                                    | MG_FEATURES_CGI
21435|      1|#endif
21436|       |#if defined(USE_IPV6)
21437|       |	                                    | MG_FEATURES_IPV6
21438|       |#endif
21439|       |#if defined(USE_WEBSOCKET)
21440|       |	                                    | MG_FEATURES_WEBSOCKET
21441|       |#endif
21442|       |#if defined(USE_LUA)
21443|       |	                                    | MG_FEATURES_LUA
21444|       |#endif
21445|       |#if defined(USE_DUKTAPE)
21446|       |	                                    | MG_FEATURES_SSJS
21447|       |#endif
21448|      1|#if !defined(NO_CACHING)
21449|      1|	                                    | MG_FEATURES_CACHE
21450|      1|#endif
21451|       |#if defined(USE_SERVER_STATS)
21452|       |	                                    | MG_FEATURES_STATS
21453|       |#endif
21454|       |#if defined(USE_ZLIB)
21455|       |	                                    | MG_FEATURES_COMPRESSION
21456|       |#endif
21457|       |#if defined(USE_HTTP2)
21458|       |	                                    | MG_FEATURES_HTTP2
21459|       |#endif
21460|       |#if defined(USE_X_DOM_SOCKET)
21461|       |	                                    | MG_FEATURES_X_DOMAIN_SOCKET
21462|       |#endif
21463|       |
21464|       |	/* Set some extra bits not defined in the API documentation.
21465|       |	 * These bits may change without further notice. */
21466|       |#if defined(MG_LEGACY_INTERFACE)
21467|       |	                                    | 0x80000000u
21468|       |#endif
21469|       |#if defined(MG_EXPERIMENTAL_INTERFACES)
21470|       |	                                    | 0x40000000u
21471|       |#endif
21472|      1|#if !defined(NO_RESPONSE_BUFFERING)
21473|      1|	                                    | 0x20000000u
21474|      1|#endif
21475|       |#if defined(MEMORY_DEBUGGING)
21476|       |	                                    | 0x10000000u
21477|       |#endif
21478|      1|	    ;
21479|      1|	return (feature & feature_set);
21480|      1|}
mg_init_library:
22339|      1|{
22340|      1|	unsigned features_to_init = mg_check_feature(features & 0xFFu);
22341|      1|	unsigned features_inited = features_to_init;
22342|       |
22343|      1|	if (mg_init_library_called <= 0) {
  ------------------
  |  Branch (22343:6): [True: 1, False: 0]
  ------------------
22344|       |		/* Not initialized yet */
22345|      1|		if (0 != pthread_mutex_init(&global_lock_mutex, NULL)) {
  ------------------
  |  Branch (22345:7): [True: 0, False: 1]
  ------------------
22346|      0|			return 0;
22347|      0|		}
22348|      1|	}
22349|       |
22350|      1|	mg_global_lock();
22351|       |
22352|      1|	if (mg_init_library_called <= 0) {
  ------------------
  |  Branch (22352:6): [True: 1, False: 0]
  ------------------
22353|      1|		int i, len;
22354|       |
22355|       |#if defined(_WIN32)
22356|       |		int file_mutex_init = 1;
22357|       |		int wsa = 1;
22358|       |#else
22359|      1|		int mutexattr_init = 1;
22360|      1|#endif
22361|      1|		int failed = 1;
22362|      1|		int key_create = pthread_key_create(&sTlsKey, tls_dtor);
22363|       |
22364|      1|		if (key_create == 0) {
  ------------------
  |  Branch (22364:7): [True: 1, False: 0]
  ------------------
22365|       |#if defined(_WIN32)
22366|       |			file_mutex_init =
22367|       |			    pthread_mutex_init(&global_log_file_lock, &pthread_mutex_attr);
22368|       |			if (file_mutex_init == 0) {
22369|       |				/* Start WinSock */
22370|       |				WSADATA data;
22371|       |				failed = wsa = WSAStartup(MAKEWORD(2, 2), &data);
22372|       |			}
22373|       |#else
22374|      1|			mutexattr_init = pthread_mutexattr_init(&pthread_mutex_attr);
22375|      1|			if (mutexattr_init == 0) {
  ------------------
  |  Branch (22375:8): [True: 1, False: 0]
  ------------------
22376|      1|				failed = pthread_mutexattr_settype(&pthread_mutex_attr,
22377|      1|				                                   PTHREAD_MUTEX_RECURSIVE);
22378|      1|			}
22379|      1|#endif
22380|      1|		}
22381|       |
22382|      1|		if (failed) {
  ------------------
  |  Branch (22382:7): [True: 0, False: 1]
  ------------------
22383|       |#if defined(_WIN32)
22384|       |			if (wsa == 0) {
22385|       |				(void)WSACleanup();
22386|       |			}
22387|       |			if (file_mutex_init == 0) {
22388|       |				(void)pthread_mutex_destroy(&global_log_file_lock);
22389|       |			}
22390|       |#else
22391|      0|			if (mutexattr_init == 0) {
  ------------------
  |  Branch (22391:8): [True: 0, False: 0]
  ------------------
22392|      0|				(void)pthread_mutexattr_destroy(&pthread_mutex_attr);
22393|      0|			}
22394|      0|#endif
22395|      0|			if (key_create == 0) {
  ------------------
  |  Branch (22395:8): [True: 0, False: 0]
  ------------------
22396|      0|				(void)pthread_key_delete(sTlsKey);
22397|      0|			}
22398|      0|			mg_global_unlock();
22399|      0|			(void)pthread_mutex_destroy(&global_lock_mutex);
22400|      0|			return 0;
22401|      0|		}
22402|       |
22403|      1|		len = 1;
22404|     17|		for (i = 0; http_methods[i].name != NULL; i++) {
  ------------------
  |  Branch (22404:15): [True: 16, False: 1]
  ------------------
22405|     16|			size_t sl = strlen(http_methods[i].name);
22406|     16|			len += (int)sl;
22407|     16|			if (i > 0) {
  ------------------
  |  Branch (22407:8): [True: 15, False: 1]
  ------------------
22408|     15|				len += 2;
22409|     15|			}
22410|     16|		}
22411|      1|		all_methods = (char *)mg_malloc(len);
22412|      1|		if (!all_methods) {
  ------------------
  |  Branch (22412:7): [True: 0, False: 1]
  ------------------
22413|       |			/* Must never happen */
22414|      0|			mg_global_unlock();
22415|      0|			(void)pthread_mutex_destroy(&global_lock_mutex);
22416|      0|			return 0;
22417|      0|		}
22418|      1|		all_methods[0] = 0;
22419|     17|		for (i = 0; http_methods[i].name != NULL; i++) {
  ------------------
  |  Branch (22419:15): [True: 16, False: 1]
  ------------------
22420|     16|			if (i > 0) {
  ------------------
  |  Branch (22420:8): [True: 15, False: 1]
  ------------------
22421|     15|				strcat(all_methods, ", ");
22422|     15|				strcat(all_methods, http_methods[i].name);
22423|     15|			} else {
22424|      1|				strcpy(all_methods, http_methods[i].name);
22425|      1|			}
22426|     16|		}
22427|      1|	}
22428|       |
22429|       |#if defined(USE_LUA)
22430|       |	lua_init_optional_libraries();
22431|       |#endif
22432|       |
22433|      1|#if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1)                      \
22434|      1|     || defined(OPENSSL_API_3_0))                                              \
22435|      1|    && !defined(NO_SSL)
22436|       |
22437|      1|	if (features_to_init & MG_FEATURES_SSL) {
  ------------------
  |  Branch (22437:6): [True: 0, False: 1]
  ------------------
22438|      0|		if (!mg_openssl_initialized) {
  ------------------
  |  Branch (22438:7): [True: 0, False: 0]
  ------------------
22439|      0|			char ebuf[128];
22440|      0|			if (initialize_openssl(ebuf, sizeof(ebuf))) {
  ------------------
  |  Branch (22440:8): [True: 0, False: 0]
  ------------------
22441|      0|				mg_openssl_initialized = 1;
22442|      0|			} else {
22443|      0|				(void)ebuf;
22444|      0|				DEBUG_TRACE("Initializing SSL failed: %s", ebuf);
  ------------------
  |  |  243|      0|	do {                                                                       \
  |  |  244|      0|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
22445|      0|				features_inited &= ~((unsigned)(MG_FEATURES_SSL));
22446|      0|			}
22447|      0|		} else {
22448|       |			/* ssl already initialized */
22449|      0|		}
22450|      0|	}
22451|       |
22452|      1|#endif
22453|       |
22454|      1|	if (mg_init_library_called <= 0) {
  ------------------
  |  Branch (22454:6): [True: 1, False: 0]
  ------------------
22455|      1|		mg_init_library_called = 1;
22456|      1|	} else {
22457|      0|		mg_init_library_called++;
22458|      0|	}
22459|      1|	mg_global_unlock();
22460|       |
22461|      1|	return features_inited;
22462|      1|}
civetweb.c:get_option_index:
 3160|      2|{
 3161|      2|	int i;
 3162|       |
 3163|     17|	for (i = 0; config_options[i].name != NULL; i++) {
  ------------------
  |  Branch (3163:14): [True: 17, False: 0]
  ------------------
 3164|     17|		if (strcmp(config_options[i].name, name) == 0) {
  ------------------
  |  Branch (3164:7): [True: 2, False: 15]
  ------------------
 3165|      2|			return i;
 3166|      2|		}
 3167|     17|	}
 3168|      0|	return -1;
 3169|      2|}
civetweb.c:mg_strdup_ctx:
 3063|     33|{
 3064|     33|	return mg_strndup_ctx(str, strlen(str), ctx);
 3065|     33|}
civetweb.c:mg_strndup_ctx:
 3048|     34|{
 3049|     34|	char *p;
 3050|     34|	(void)ctx; /* Avoid Visual Studio warning if USE_SERVER_STATS is not
 3051|       |	            * defined */
 3052|       |
 3053|     34|	if ((p = (char *)mg_malloc_ctx(len + 1, ctx)) != NULL) {
  ------------------
  |  | 1497|     34|#define mg_malloc_ctx(a, c) mg_malloc(a)
  ------------------
  |  Branch (3053:6): [True: 34, False: 0]
  ------------------
 3054|     34|		mg_strlcpy(p, ptr, len + 1);
 3055|     34|	}
 3056|       |
 3057|     34|	return p;
 3058|     34|}
civetweb.c:mg_malloc:
 1475|     85|{
 1476|     85|	return malloc(a);
 1477|     85|}
civetweb.c:mg_free:
 1493|     90|{
 1494|     90|	free(a);
 1495|     90|}
civetweb.c:next_option:
 3900|      3|{
 3901|      3|	int end;
 3902|       |
 3903|      3|reparse:
 3904|      3|	if (val == NULL || list == NULL || *list == '\0') {
  ------------------
  |  Branch (3904:6): [True: 0, False: 3]
  |  Branch (3904:21): [True: 1, False: 2]
  |  Branch (3904:37): [True: 1, False: 1]
  ------------------
 3905|       |		/* End of the list */
 3906|      2|		return NULL;
 3907|      2|	}
 3908|       |
 3909|       |	/* Skip over leading LWS */
 3910|      1|	while (*list == ' ' || *list == '\t')
  ------------------
  |  Branch (3910:9): [True: 0, False: 1]
  |  Branch (3910:25): [True: 0, False: 1]
  ------------------
 3911|      0|		list++;
 3912|       |
 3913|      1|	val->ptr = list;
 3914|      1|	if ((list = strchr(val->ptr, ',')) != NULL) {
  ------------------
  |  Branch (3914:6): [True: 0, False: 1]
  ------------------
 3915|       |		/* Comma found. Store length and shift the list ptr */
 3916|      0|		val->len = ((size_t)(list - val->ptr));
 3917|      0|		list++;
 3918|      1|	} else {
 3919|       |		/* This value is the last one */
 3920|      1|		list = val->ptr + strlen(val->ptr);
 3921|      1|		val->len = ((size_t)(list - val->ptr));
 3922|      1|	}
 3923|       |
 3924|       |	/* Adjust length for trailing LWS */
 3925|      1|	end = (int)val->len - 1;
 3926|      1|	while (end >= 0 && ((val->ptr[end] == ' ') || (val->ptr[end] == '\t')))
  ------------------
  |  Branch (3926:9): [True: 1, False: 0]
  |  Branch (3926:22): [True: 0, False: 1]
  |  Branch (3926:48): [True: 0, False: 1]
  ------------------
 3927|      0|		end--;
 3928|      1|	val->len = (size_t)(end) + (size_t)(1);
 3929|       |
 3930|      1|	if (val->len == 0) {
  ------------------
  |  Branch (3930:6): [True: 0, False: 1]
  ------------------
 3931|       |		/* Ignore any empty entries. */
 3932|      0|		goto reparse;
 3933|      0|	}
 3934|       |
 3935|      1|	if (eq_val != NULL) {
  ------------------
  |  Branch (3935:6): [True: 0, False: 1]
  ------------------
 3936|       |		/* Value has form "x=y", adjust pointers and lengths
 3937|       |		 * so that val points to "x", and eq_val points to "y". */
 3938|      0|		eq_val->len = 0;
 3939|      0|		eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
 3940|      0|		if (eq_val->ptr != NULL) {
  ------------------
  |  Branch (3940:7): [True: 0, False: 0]
  ------------------
 3941|      0|			eq_val->ptr++; /* Skip over '=' character */
 3942|      0|			eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
 3943|      0|			val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
 3944|      0|		}
 3945|      0|	}
 3946|       |
 3947|      1|	return list;
 3948|      1|}
civetweb.c:mg_vsnprintf:
 3100|     51|{
 3101|     51|	int n, ok;
 3102|       |
 3103|     51|	if (buflen == 0) {
  ------------------
  |  Branch (3103:6): [True: 0, False: 51]
  ------------------
 3104|      0|		if (truncated) {
  ------------------
  |  Branch (3104:7): [True: 0, False: 0]
  ------------------
 3105|      0|			*truncated = 1;
 3106|      0|		}
 3107|      0|		return;
 3108|      0|	}
 3109|       |
 3110|     51|#if defined(__clang__)
 3111|     51|#pragma clang diagnostic push
 3112|     51|#pragma clang diagnostic ignored "-Wformat-nonliteral"
 3113|       |	/* Using fmt as a non-literal is intended here, since it is mostly called
 3114|       |	 * indirectly by mg_snprintf */
 3115|     51|#endif
 3116|       |
 3117|     51|	n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
  ------------------
  |  |  897|     51|#define vsnprintf_impl vsnprintf
  ------------------
 3118|     51|	ok = (n >= 0) && ((size_t)n < buflen);
  ------------------
  |  Branch (3118:7): [True: 51, False: 0]
  |  Branch (3118:19): [True: 51, False: 0]
  ------------------
 3119|       |
 3120|     51|#if defined(__clang__)
 3121|     51|#pragma clang diagnostic pop
 3122|     51|#endif
 3123|       |
 3124|     51|	if (ok) {
  ------------------
  |  Branch (3124:6): [True: 51, False: 0]
  ------------------
 3125|     51|		if (truncated) {
  ------------------
  |  Branch (3125:7): [True: 0, False: 51]
  ------------------
 3126|      0|			*truncated = 0;
 3127|      0|		}
 3128|     51|	} else {
 3129|      0|		if (truncated) {
  ------------------
  |  Branch (3129:7): [True: 0, False: 0]
  ------------------
 3130|      0|			*truncated = 1;
 3131|      0|		}
 3132|      0|		mg_cry_internal(conn,
  ------------------
  |  | 2584|      0|	mg_cry_internal_wrap(conn, NULL, __func__, __LINE__, fmt, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (2584:60): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3133|      0|		                "truncating vsnprintf buffer: [%.*s]",
 3134|      0|		                (int)((buflen > 200) ? 200 : (buflen - 1)),
 3135|      0|		                buf);
 3136|      0|		n = (int)buflen - 1;
 3137|      0|	}
 3138|     51|	buf[n] = '\0';
 3139|     51|}
civetweb.c:mg_realloc:
 1487|      2|{
 1488|      2|	return realloc(a, b);
 1489|      2|}
civetweb.c:set_close_on_exec:
 5680|      1|{
 5681|       |#if defined(__ZEPHYR__)
 5682|       |	(void)fd;
 5683|       |	(void)conn;
 5684|       |	(void)ctx;
 5685|       |#else
 5686|      1|	if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
  ------------------
  |  Branch (5686:6): [True: 0, False: 1]
  ------------------
 5687|      0|		if (conn || ctx) {
  ------------------
  |  Branch (5687:7): [True: 0, False: 0]
  |  Branch (5687:15): [True: 0, False: 0]
  ------------------
 5688|      0|			struct mg_connection fc;
 5689|      0|			mg_cry_internal((conn ? conn : fake_connection(&fc, ctx)),
  ------------------
  |  | 2584|      0|	mg_cry_internal_wrap(conn, NULL, __func__, __LINE__, fmt, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (2584:23): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 5690|      0|			                "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
 5691|      0|			                __func__,
 5692|      0|			                strerror(ERRNO));
 5693|      0|		}
 5694|      0|	}
 5695|      1|#endif
 5696|      1|}
civetweb.c:mg_poll:
 5942|      3|{
 5943|       |	/* Call poll, but only for a maximum time of a few seconds.
 5944|       |	 * This will allow to stop the server after some seconds, instead
 5945|       |	 * of having to wait for a long socket timeout. */
 5946|      3|	int ms_now = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
  ------------------
  |  |  473|      3|#define SOCKET_TIMEOUT_QUANTUM (2000) /* in ms */
  ------------------
 5947|       |
 5948|      3|	int check_pollerr = 0;
 5949|      3|	if ((n == 1) && ((pfd[0].events & POLLERR) == 0)) {
  ------------------
  |  Branch (5949:6): [True: 3, False: 0]
  |  Branch (5949:18): [True: 3, False: 0]
  ------------------
 5950|       |		/* If we wait for only one file descriptor, wait on error as well */
 5951|      3|		pfd[0].events |= POLLERR;
 5952|      3|		check_pollerr = 1;
 5953|      3|	}
 5954|       |
 5955|      3|	do {
 5956|      3|		int result;
 5957|       |
 5958|      3|		if (!STOP_FLAG_IS_ZERO(&*stop_flag)) {
  ------------------
  |  | 2322|      3|#define STOP_FLAG_IS_ZERO(f) ((*(f)) == 0)
  ------------------
  |  Branch (5958:7): [True: 0, False: 3]
  ------------------
 5959|       |			/* Shut down signal */
 5960|      0|			return -2;
 5961|      0|		}
 5962|       |
 5963|      3|		if ((milliseconds >= 0) && (milliseconds < ms_now)) {
  ------------------
  |  Branch (5963:7): [True: 3, False: 0]
  |  Branch (5963:30): [True: 0, False: 3]
  ------------------
 5964|      0|			ms_now = milliseconds;
 5965|      0|		}
 5966|       |
 5967|      3|		result = poll(pfd, n, ms_now);
 5968|      3|		if (result != 0) {
  ------------------
  |  Branch (5968:7): [True: 0, False: 3]
  ------------------
 5969|      0|			int err = ERRNO;
  ------------------
  |  |  924|      0|#define ERRNO (errno)
  ------------------
 5970|      0|			if ((result == 1) || (!ERROR_TRY_AGAIN(err))) {
  ------------------
  |  |  448|      0|	(((err) == EAGAIN) || ((err) == EWOULDBLOCK) || ((err) == EINTR))
  |  |  ------------------
  |  |  |  Branch (448:3): [True: 0, False: 0]
  |  |  |  Branch (448:24): [True: 0, False: 0]
  |  |  |  Branch (448:50): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (5970:8): [True: 0, False: 0]
  ------------------
 5971|       |				/* Poll returned either success (1) or error (-1).
 5972|       |				 * Forward both to the caller. */
 5973|      0|				if ((check_pollerr)
  ------------------
  |  Branch (5973:9): [True: 0, False: 0]
  ------------------
 5974|      0|				    && ((pfd[0].revents & (POLLIN | POLLOUT | POLLERR))
  ------------------
  |  Branch (5974:12): [True: 0, False: 0]
  ------------------
 5975|      0|				        == POLLERR)) {
 5976|       |					/* One and only file descriptor returned error */
 5977|      0|					return -1;
 5978|      0|				}
 5979|      0|				return result;
 5980|      0|			}
 5981|      0|		}
 5982|       |
 5983|       |		/* Poll returned timeout (0). */
 5984|      3|		if (milliseconds > 0) {
  ------------------
  |  Branch (5984:7): [True: 3, False: 0]
  ------------------
 5985|      3|			milliseconds -= ms_now;
 5986|      3|		}
 5987|       |
 5988|      3|	} while (milliseconds > 0);
  ------------------
  |  Branch (5988:11): [True: 0, False: 3]
  ------------------
 5989|       |
 5990|       |	/* timeout: return 0 */
 5991|      3|	return 0;
 5992|      3|}
civetweb.c:mg_get_current_time_ns:
 1677|      3|{
 1678|      3|	struct timespec tsnow;
 1679|      3|	clock_gettime(CLOCK_REALTIME, &tsnow);
 1680|      3|	return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
 1681|      3|}
civetweb.c:mg_snprintf:
 3149|     51|{
 3150|     51|	va_list ap;
 3151|       |
 3152|     51|	va_start(ap, fmt);
 3153|     51|	mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
 3154|     51|	va_end(ap);
 3155|     51|}
civetweb.c:mg_strlcpy:
 3003|     34|{
 3004|    237|	for (; *src != '\0' && n > 1; n--) {
  ------------------
  |  Branch (3004:9): [True: 203, False: 34]
  |  Branch (3004:25): [True: 203, False: 0]
  ------------------
 3005|    203|		*dst++ = *src++;
 3006|    203|	}
 3007|     34|	*dst = '\0';
 3008|     34|}
civetweb.c:mg_calloc:
 1481|      4|{
 1482|      4|	return calloc(a, b);
 1483|      4|}
civetweb.c:mg_strdup:
 3069|      1|{
 3070|      1|	return mg_strndup_ctx(str, strlen(str), NULL);
 3071|      1|}
civetweb.c:is_valid_port:
 9232|      2|{
 9233|      2|	return (port <= 0xffff);
 9234|      2|}
civetweb.c:mg_join_thread:
 5758|     51|{
 5759|     51|	int result;
 5760|       |
 5761|     51|	result = pthread_join(threadid, NULL);
 5762|     51|	return result;
 5763|     51|}
civetweb.c:free_context:
20241|      1|{
20242|      1|	int i;
20243|      1|	struct mg_handler_info *tmp_rh;
20244|       |
20245|      1|	if (ctx == NULL) {
  ------------------
  |  Branch (20245:6): [True: 0, False: 1]
  ------------------
20246|      0|		return;
20247|      0|	}
20248|       |
20249|       |	/* Call user callback */
20250|      1|	if (ctx->callbacks.exit_context) {
  ------------------
  |  Branch (20250:6): [True: 0, False: 1]
  ------------------
20251|      0|		ctx->callbacks.exit_context(ctx);
20252|      0|	}
20253|       |
20254|       |	/* All threads exited, no sync is needed. Destroy thread mutex and
20255|       |	 * condvars
20256|       |	 */
20257|      1|	(void)pthread_mutex_destroy(&ctx->thread_mutex);
20258|       |
20259|       |#if defined(ALTERNATIVE_QUEUE)
20260|       |	mg_free(ctx->client_socks);
20261|       |	if (ctx->client_wait_events != NULL) {
20262|       |		for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
20263|       |			event_destroy(ctx->client_wait_events[i]);
20264|       |		}
20265|       |		mg_free(ctx->client_wait_events);
20266|       |	}
20267|       |#else
20268|      1|	(void)pthread_cond_destroy(&ctx->sq_empty);
20269|      1|	(void)pthread_cond_destroy(&ctx->sq_full);
20270|      1|	mg_free(ctx->squeue);
20271|      1|#endif
20272|       |
20273|       |	/* Destroy other context global data structures mutex */
20274|      1|	(void)pthread_mutex_destroy(&ctx->nonce_mutex);
20275|       |
20276|       |#if defined(USE_LUA)
20277|       |	(void)pthread_mutex_destroy(&ctx->lua_bg_mutex);
20278|       |#endif
20279|       |
20280|       |	/* Deallocate config parameters */
20281|     62|	for (i = 0; i < NUM_OPTIONS; i++) {
  ------------------
  |  Branch (20281:14): [True: 61, False: 1]
  ------------------
20282|     61|		if (ctx->dd.config[i] != NULL) {
  ------------------
  |  Branch (20282:7): [True: 33, False: 28]
  ------------------
20283|       |#if defined(_MSC_VER)
20284|       |#pragma warning(suppress : 6001)
20285|       |#endif
20286|     33|			mg_free(ctx->dd.config[i]);
20287|     33|		}
20288|     61|	}
20289|       |
20290|       |	/* Deallocate request handlers */
20291|      1|	while (ctx->dd.handlers) {
  ------------------
  |  Branch (20291:9): [True: 0, False: 1]
  ------------------
20292|      0|		tmp_rh = ctx->dd.handlers;
20293|      0|		ctx->dd.handlers = tmp_rh->next;
20294|      0|		mg_free(tmp_rh->uri);
20295|      0|		mg_free(tmp_rh);
20296|      0|	}
20297|       |
20298|       |#if defined(USE_MBEDTLS)
20299|       |	if (ctx->dd.ssl_ctx != NULL) {
20300|       |		mbed_sslctx_uninit(ctx->dd.ssl_ctx);
20301|       |		mg_free(ctx->dd.ssl_ctx);
20302|       |		ctx->dd.ssl_ctx = NULL;
20303|       |	}
20304|       |
20305|       |#elif !defined(NO_SSL)
20306|       |	/* Deallocate SSL context */
20307|      1|	if (ctx->dd.ssl_ctx != NULL) {
  ------------------
  |  Branch (20307:6): [True: 0, False: 1]
  ------------------
20308|      0|		void *ssl_ctx = (void *)ctx->dd.ssl_ctx;
20309|      0|		int callback_ret =
20310|      0|		    (ctx->callbacks.external_ssl_ctx == NULL)
  ------------------
  |  Branch (20310:7): [True: 0, False: 0]
  ------------------
20311|      0|		        ? 0
20312|      0|		        : (ctx->callbacks.external_ssl_ctx(&ssl_ctx, ctx->user_data));
20313|       |
20314|      0|		if (callback_ret == 0) {
  ------------------
  |  Branch (20314:7): [True: 0, False: 0]
  ------------------
20315|      0|			SSL_CTX_free(ctx->dd.ssl_ctx);
  ------------------
  |  |  124|      0|#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
  ------------------
20316|      0|		}
20317|       |		/* else: ignore error and omit SSL_CTX_free in case
20318|       |		 * callback_ret is 1 */
20319|      0|	}
20320|      1|#endif /* !NO_SSL */
20321|       |
20322|       |	/* Deallocate worker thread ID array */
20323|      1|	mg_free(ctx->worker_threadids);
20324|       |
20325|       |	/* Deallocate worker thread ID array */
20326|      1|	mg_free(ctx->worker_connections);
20327|       |
20328|       |	/* deallocate system name string */
20329|      1|	mg_free(ctx->systemName);
20330|       |
20331|       |	/* Deallocate context itself */
20332|      1|	mg_free(ctx);
20333|      1|}
civetweb.c:legacy_init:
20428|      1|{
20429|      1|	const char *ports_option = config_options[LISTENING_PORTS].default_value;
20430|       |
20431|      1|	if (options) {
  ------------------
  |  Branch (20431:6): [True: 1, False: 0]
  ------------------
20432|      1|		const char **run_options = options;
20433|      1|		const char *optname = config_options[LISTENING_PORTS].name;
20434|       |
20435|       |		/* Try to find the "listening_ports" option */
20436|      3|		while (*run_options) {
  ------------------
  |  Branch (20436:10): [True: 2, False: 1]
  ------------------
20437|      2|			if (!strcmp(*run_options, optname)) {
  ------------------
  |  Branch (20437:8): [True: 1, False: 1]
  ------------------
20438|      1|				ports_option = run_options[1];
20439|      1|			}
20440|      2|			run_options += 2;
20441|      2|		}
20442|      1|	}
20443|       |
20444|      1|	if (is_ssl_port_used(ports_option)) {
  ------------------
  |  Branch (20444:6): [True: 0, False: 1]
  ------------------
20445|       |		/* Initialize with SSL support */
20446|      0|		mg_init_library(MG_FEATURES_TLS);
20447|      1|	} else {
20448|       |		/* Initialize without SSL support */
20449|      1|		mg_init_library(MG_FEATURES_DEFAULT);
20450|      1|	}
20451|      1|}
civetweb.c:is_ssl_port_used:
15671|      2|{
15672|      2|	if (ports) {
  ------------------
  |  Branch (15672:6): [True: 2, False: 0]
  ------------------
15673|       |		/* There are several different allowed syntax variants:
15674|       |		 * - "80" for a single port using every network interface
15675|       |		 * - "localhost:80" for a single port using only localhost
15676|       |		 * - "80,localhost:8080" for two ports, one bound to localhost
15677|       |		 * - "80,127.0.0.1:8084,[::1]:8086" for three ports, one bound
15678|       |		 *   to IPv4 localhost, one to IPv6 localhost
15679|       |		 * - "+80" use port 80 for IPv4 and IPv6
15680|       |		 * - "+80r,+443s" port 80 (HTTP) is a redirect to port 443 (HTTPS),
15681|       |		 *   for both: IPv4 and IPv4
15682|       |		 * - "+443s,localhost:8080" port 443 (HTTPS) for every interface,
15683|       |		 *   additionally port 8080 bound to localhost connections
15684|       |		 *
15685|       |		 * If we just look for 's' anywhere in the string, "localhost:80"
15686|       |		 * will be detected as SSL (false positive).
15687|       |		 * Looking for 's' after a digit may cause false positives in
15688|       |		 * "my24service:8080".
15689|       |		 * Looking from 's' backward if there are only ':' and numbers
15690|       |		 * before will not work for "24service:8080" (non SSL, port 8080)
15691|       |		 * or "24s" (SSL, port 24).
15692|       |		 *
15693|       |		 * Remark: Initially hostnames were not allowed to start with a
15694|       |		 * digit (according to RFC 952), this was allowed later (RFC 1123,
15695|       |		 * Section 2.1).
15696|       |		 *
15697|       |		 * To get this correct, the entire string must be parsed as a whole,
15698|       |		 * reading it as a list element for element and parsing with an
15699|       |		 * algorithm equivalent to parse_port_string.
15700|       |		 *
15701|       |		 * In fact, we use local interface names here, not arbitrary
15702|       |		 * hostnames, so in most cases the only name will be "localhost".
15703|       |		 *
15704|       |		 * So, for now, we use this simple algorithm, that may still return
15705|       |		 * a false positive in bizarre cases.
15706|       |		 */
15707|      2|		int i;
15708|      2|		int portslen = (int)strlen(ports);
15709|      2|		char prevIsNumber = 0;
15710|       |
15711|      4|		for (i = 0; i < portslen; i++) {
  ------------------
  |  Branch (15711:15): [True: 2, False: 2]
  ------------------
15712|      2|			if (prevIsNumber && (ports[i] == 's' || ports[i] == 'r')) {
  ------------------
  |  Branch (15712:8): [True: 0, False: 2]
  |  Branch (15712:25): [True: 0, False: 0]
  |  Branch (15712:44): [True: 0, False: 0]
  ------------------
15713|      0|				return 1;
15714|      0|			}
15715|      2|			if (ports[i] >= '0' && ports[i] <= '9') {
  ------------------
  |  Branch (15715:8): [True: 2, False: 0]
  |  Branch (15715:27): [True: 2, False: 0]
  ------------------
15716|      2|				prevIsNumber = 1;
15717|      2|			} else {
15718|      0|				prevIsNumber = 0;
15719|      0|			}
15720|      2|		}
15721|      2|	}
15722|      2|	return 0;
15723|      2|}
civetweb.c:get_random:
 5910|      1|{
 5911|      1|	static uint64_t lfsr = 0; /* Linear feedback shift register */
 5912|      1|	static uint64_t lcg = 0;  /* Linear congruential generator */
 5913|      1|	uint64_t now = mg_get_current_time_ns();
 5914|       |
 5915|      1|	if (lfsr == 0) {
  ------------------
  |  Branch (5915:6): [True: 1, False: 0]
  ------------------
 5916|       |		/* lfsr will be only 0 if has not been initialized,
 5917|       |		 * so this code is called only once. */
 5918|      1|		lfsr = mg_get_current_time_ns();
 5919|      1|		lcg = mg_get_current_time_ns();
 5920|      1|	} else {
 5921|       |		/* Get the next step of both random number generators. */
 5922|      0|		lfsr = (lfsr >> 1)
 5923|      0|		       | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
 5924|      0|		          << 63);
 5925|      0|		lcg = lcg * 6364136223846793005LL + 1442695040888963407LL;
 5926|      0|	}
 5927|       |
 5928|       |	/* Combining two pseudo-random number generators and a high resolution
 5929|       |	 * part
 5930|       |	 * of the current server time will make it hard (impossible?) to guess
 5931|       |	 * the
 5932|       |	 * next number. */
 5933|      1|	return (lfsr ^ lcg ^ now);
 5934|      1|}
civetweb.c:mg_atomic_inc:
 1122|     51|{
 1123|     51|	ptrdiff_t ret;
 1124|       |
 1125|       |#if defined(_WIN64) && !defined(NO_ATOMICS)
 1126|       |	ret = InterlockedIncrement64(addr);
 1127|       |#elif defined(_WIN32) && !defined(NO_ATOMICS)
 1128|       |	ret = InterlockedIncrement(addr);
 1129|       |#elif defined(__GNUC__)                                                        \
 1130|       |    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))           \
 1131|       |    && !defined(NO_ATOMICS)
 1132|     51|	ret = __sync_add_and_fetch(addr, 1);
 1133|       |#else
 1134|       |	mg_global_lock();
 1135|       |	ret = (++(*addr));
 1136|       |	mg_global_unlock();
 1137|       |#endif
 1138|     51|	return ret;
 1139|     51|}
civetweb.c:get_system_name:
20381|      1|{
20382|       |#if defined(_WIN32)
20383|       |	char name[128];
20384|       |	DWORD dwVersion = 0;
20385|       |	DWORD dwMajorVersion = 0;
20386|       |	DWORD dwMinorVersion = 0;
20387|       |	DWORD dwBuild = 0;
20388|       |	BOOL wowRet, isWoW = FALSE;
20389|       |
20390|       |#if defined(_MSC_VER)
20391|       |#pragma warning(push)
20392|       |	/* GetVersion was declared deprecated */
20393|       |#pragma warning(disable : 4996)
20394|       |#endif
20395|       |	dwVersion = GetVersion();
20396|       |#if defined(_MSC_VER)
20397|       |#pragma warning(pop)
20398|       |#endif
20399|       |
20400|       |	dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
20401|       |	dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
20402|       |	dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
20403|       |	(void)dwBuild;
20404|       |
20405|       |	wowRet = IsWow64Process(GetCurrentProcess(), &isWoW);
20406|       |
20407|       |	sprintf(name,
20408|       |	        "Windows %u.%u%s",
20409|       |	        (unsigned)dwMajorVersion,
20410|       |	        (unsigned)dwMinorVersion,
20411|       |	        (wowRet ? (isWoW ? " (WoW64)" : "") : " (?)"));
20412|       |
20413|       |	*sysName = mg_strdup(name);
20414|       |
20415|       |#elif defined(__ZEPHYR__)
20416|       |	*sysName = mg_strdup("Zephyr OS");
20417|       |#else
20418|      1|	struct utsname name;
20419|      1|	memset(&name, 0, sizeof(name));
20420|      1|	uname(&name);
20421|      1|	*sysName = mg_strdup(name.sysname);
20422|      1|#endif
20423|      1|}
civetweb.c:set_gpass_option:
17628|      1|{
17629|      1|	if (phys_ctx) {
  ------------------
  |  Branch (17629:6): [True: 1, False: 0]
  ------------------
17630|      1|		struct mg_file file = STRUCT_FILE_INITIALIZER;
  ------------------
  |  | 1892|      1|	{                                                                          \
  |  | 1893|      1|		{(uint64_t)0, (time_t)0, 0, 0, 0},                                     \
  |  | 1894|      1|		{                                                                      \
  |  | 1895|      1|			(FILE *)NULL                                                       \
  |  | 1896|      1|		}                                                                      \
  |  | 1897|      1|	}
  ------------------
17631|      1|		const char *path;
17632|      1|		struct mg_connection fc;
17633|      1|		if (!dom_ctx) {
  ------------------
  |  Branch (17633:7): [True: 1, False: 0]
  ------------------
17634|      1|			dom_ctx = &(phys_ctx->dd);
17635|      1|		}
17636|      1|		path = dom_ctx->config[GLOBAL_PASSWORDS_FILE];
17637|      1|		if ((path != NULL)
  ------------------
  |  Branch (17637:7): [True: 0, False: 1]
  ------------------
17638|      1|		    && !mg_stat(fake_connection(&fc, phys_ctx), path, &file.stat)) {
  ------------------
  |  Branch (17638:10): [True: 0, False: 0]
  ------------------
17639|      0|			mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
17640|      0|			                    "Cannot open %s: %s",
17641|      0|			                    path,
17642|      0|			                    strerror(ERRNO));
17643|      0|			return 0;
17644|      0|		}
17645|      1|		return 1;
17646|      1|	}
17647|      0|	return 0;
17648|      1|}
civetweb.c:init_ssl_ctx:
17477|      1|{
17478|      1|	void *ssl_ctx = 0;
17479|      1|	int callback_ret;
17480|      1|	const char *pem;
17481|      1|	const char *chain;
17482|      1|	char ebuf[128];
17483|       |
17484|      1|	if (!phys_ctx) {
  ------------------
  |  Branch (17484:6): [True: 0, False: 1]
  ------------------
17485|      0|		return 0;
17486|      0|	}
17487|       |
17488|      1|	if (!dom_ctx) {
  ------------------
  |  Branch (17488:6): [True: 1, False: 0]
  ------------------
17489|      1|		dom_ctx = &(phys_ctx->dd);
17490|      1|	}
17491|       |
17492|      1|	if (!is_ssl_port_used(dom_ctx->config[LISTENING_PORTS])) {
  ------------------
  |  Branch (17492:6): [True: 1, False: 0]
  ------------------
17493|       |		/* No SSL port is set. No need to setup SSL. */
17494|      1|		return 1;
17495|      1|	}
17496|       |
17497|       |	/* Check for external SSL_CTX */
17498|      0|	callback_ret =
17499|      0|	    (phys_ctx->callbacks.external_ssl_ctx == NULL)
  ------------------
  |  Branch (17499:6): [True: 0, False: 0]
  ------------------
17500|      0|	        ? 0
17501|      0|	        : (phys_ctx->callbacks.external_ssl_ctx(&ssl_ctx,
17502|      0|	                                                phys_ctx->user_data));
17503|       |
17504|      0|	if (callback_ret < 0) {
  ------------------
  |  Branch (17504:6): [True: 0, False: 0]
  ------------------
17505|       |		/* Callback exists and returns <0: Initializing failed. */
17506|      0|		mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
17507|      0|		                    "external_ssl_ctx callback returned error: %i",
17508|      0|		                    callback_ret);
17509|      0|		return 0;
17510|      0|	} else if (callback_ret > 0) {
  ------------------
  |  Branch (17510:13): [True: 0, False: 0]
  ------------------
17511|       |		/* Callback exists and returns >0: Initializing complete,
17512|       |		 * civetweb should not modify the SSL context. */
17513|      0|		dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx;
17514|      0|		if (!initialize_openssl(ebuf, sizeof(ebuf))) {
  ------------------
  |  Branch (17514:7): [True: 0, False: 0]
  ------------------
17515|      0|			mg_cry_ctx_internal(phys_ctx, "%s", ebuf);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
17516|      0|			return 0;
17517|      0|		}
17518|      0|		return 1;
17519|      0|	}
17520|       |	/* If the callback does not exist or return 0, civetweb must initialize
17521|       |	 * the SSL context. Handle "domain" callback next. */
17522|       |
17523|       |	/* Check for external domain SSL_CTX callback. */
17524|      0|	callback_ret = (phys_ctx->callbacks.external_ssl_ctx_domain == NULL)
  ------------------
  |  Branch (17524:17): [True: 0, False: 0]
  ------------------
17525|      0|	                   ? 0
17526|      0|	                   : (phys_ctx->callbacks.external_ssl_ctx_domain(
17527|      0|	                         dom_ctx->config[AUTHENTICATION_DOMAIN],
17528|      0|	                         &ssl_ctx,
17529|      0|	                         phys_ctx->user_data));
17530|       |
17531|      0|	if (callback_ret < 0) {
  ------------------
  |  Branch (17531:6): [True: 0, False: 0]
  ------------------
17532|       |		/* Callback < 0: Error. Abort init. */
17533|      0|		mg_cry_ctx_internal(
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
17534|      0|		    phys_ctx,
17535|      0|		    "external_ssl_ctx_domain callback returned error: %i",
17536|      0|		    callback_ret);
17537|      0|		return 0;
17538|      0|	} else if (callback_ret > 0) {
  ------------------
  |  Branch (17538:13): [True: 0, False: 0]
  ------------------
17539|       |		/* Callback > 0: Consider init done. */
17540|      0|		dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx;
17541|      0|		if (!initialize_openssl(ebuf, sizeof(ebuf))) {
  ------------------
  |  Branch (17541:7): [True: 0, False: 0]
  ------------------
17542|      0|			mg_cry_ctx_internal(phys_ctx, "%s", ebuf);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
17543|      0|			return 0;
17544|      0|		}
17545|      0|		return 1;
17546|      0|	}
17547|       |	/* else: external_ssl_ctx/external_ssl_ctx_domain do not exist or return
17548|       |	 * 0, CivetWeb should continue initializing SSL */
17549|       |
17550|       |	/* If PEM file is not specified and the init_ssl callbacks
17551|       |	 * are not specified, setup will fail. */
17552|      0|	if (((pem = dom_ctx->config[SSL_CERTIFICATE]) == NULL)
  ------------------
  |  Branch (17552:6): [True: 0, False: 0]
  ------------------
17553|      0|	    && (phys_ctx->callbacks.init_ssl == NULL)
  ------------------
  |  Branch (17553:9): [True: 0, False: 0]
  ------------------
17554|      0|	    && (phys_ctx->callbacks.init_ssl_domain == NULL)) {
  ------------------
  |  Branch (17554:9): [True: 0, False: 0]
  ------------------
17555|       |		/* No certificate and no init_ssl callbacks:
17556|       |		 * Essential data to set up TLS is missing.
17557|       |		 */
17558|      0|		mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
17559|      0|		                    "Initializing SSL failed: -%s is not set",
17560|      0|		                    config_options[SSL_CERTIFICATE].name);
17561|      0|		return 0;
17562|      0|	}
17563|       |
17564|       |	/* If a certificate chain is configured, use it. */
17565|      0|	chain = dom_ctx->config[SSL_CERTIFICATE_CHAIN];
17566|      0|	if (chain == NULL) {
  ------------------
  |  Branch (17566:6): [True: 0, False: 0]
  ------------------
17567|       |		/* Default: certificate chain in PEM file */
17568|      0|		chain = pem;
17569|      0|	}
17570|      0|	if ((chain != NULL) && (*chain == 0)) {
  ------------------
  |  Branch (17570:6): [True: 0, False: 0]
  |  Branch (17570:25): [True: 0, False: 0]
  ------------------
17571|       |		/* If the chain is an empty string, don't use it. */
17572|      0|		chain = NULL;
17573|      0|	}
17574|       |
17575|      0|	if (!initialize_openssl(ebuf, sizeof(ebuf))) {
  ------------------
  |  Branch (17575:6): [True: 0, False: 0]
  ------------------
17576|      0|		mg_cry_ctx_internal(phys_ctx, "%s", ebuf);
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
17577|      0|		return 0;
17578|      0|	}
17579|       |
17580|      0|	return init_ssl_ctx_impl(phys_ctx, dom_ctx, pem, chain);
17581|      0|}
civetweb.c:set_ports_option:
15728|      1|{
15729|      1|	const char *list;
15730|      1|	int on = 1;
15731|       |#if defined(USE_IPV6)
15732|       |	int off = 0;
15733|       |#endif
15734|      1|	struct vec vec;
15735|      1|	struct socket so, *ptr;
15736|       |
15737|      1|	struct mg_pollfd *pfd;
15738|      1|	union usa usa;
15739|      1|	socklen_t len;
15740|      1|	int ip_version;
15741|       |
15742|      1|	int portsTotal = 0;
15743|      1|	int portsOk = 0;
15744|       |
15745|      1|	const char *opt_txt;
15746|      1|	long opt_listen_backlog;
15747|       |
15748|      1|	if (!phys_ctx) {
  ------------------
  |  Branch (15748:6): [True: 0, False: 1]
  ------------------
15749|      0|		return 0;
15750|      0|	}
15751|       |
15752|      1|	memset(&so, 0, sizeof(so));
15753|      1|	memset(&usa, 0, sizeof(usa));
15754|      1|	len = sizeof(usa);
15755|      1|	list = phys_ctx->dd.config[LISTENING_PORTS];
15756|       |
15757|      2|	while ((list = next_option(list, &vec, NULL)) != NULL) {
  ------------------
  |  Branch (15757:9): [True: 1, False: 1]
  ------------------
15758|       |
15759|      1|		portsTotal++;
15760|       |
15761|      1|		if (!parse_port_string(&vec, &so, &ip_version)) {
  ------------------
  |  Branch (15761:7): [True: 0, False: 1]
  ------------------
15762|      0|			mg_cry_ctx_internal(
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15763|      0|			    phys_ctx,
15764|      0|			    "%.*s: invalid port spec (entry %i). Expecting list of: %s",
15765|      0|			    (int)vec.len,
15766|      0|			    vec.ptr,
15767|      0|			    portsTotal,
15768|      0|			    "[IP_ADDRESS:]PORT[s|r]");
15769|      0|			continue;
15770|      0|		}
15771|       |
15772|      1|#if !defined(NO_SSL)
15773|      1|		if (so.is_ssl && phys_ctx->dd.ssl_ctx == NULL) {
  ------------------
  |  Branch (15773:7): [True: 0, False: 1]
  |  Branch (15773:20): [True: 0, False: 0]
  ------------------
15774|       |
15775|      0|			mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15776|      0|			                    "Cannot add SSL socket (entry %i)",
15777|      0|			                    portsTotal);
15778|      0|			continue;
15779|      0|		}
15780|      1|#endif
15781|       |		/* Create socket. */
15782|       |		/* For a list of protocol numbers (e.g., TCP==6) see:
15783|       |		 * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
15784|       |		 */
15785|      1|		if ((so.sock =
  ------------------
  |  Branch (15785:7): [True: 0, False: 1]
  ------------------
15786|      1|		         socket(so.lsa.sa.sa_family,
15787|      1|		                SOCK_STREAM,
15788|      1|		                (ip_version == 99) ? (/* LOCAL */ 0) : (/* TCP */ 6)))
  ------------------
  |  Branch (15788:19): [True: 0, False: 1]
  ------------------
15789|      1|		    == INVALID_SOCKET) {
  ------------------
  |  |  925|      1|#define INVALID_SOCKET (-1)
  ------------------
15790|       |
15791|      0|			mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15792|      0|			                    "cannot create socket (entry %i)",
15793|      0|			                    portsTotal);
15794|      0|			continue;
15795|      0|		}
15796|       |
15797|       |#if defined(_WIN32)
15798|       |		/* Windows SO_REUSEADDR lets many procs binds to a
15799|       |		 * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
15800|       |		 * if someone already has the socket -- DTL */
15801|       |		/* NOTE: If SO_EXCLUSIVEADDRUSE is used,
15802|       |		 * Windows might need a few seconds before
15803|       |		 * the same port can be used again in the
15804|       |		 * same process, so a short Sleep may be
15805|       |		 * required between mg_stop and mg_start.
15806|       |		 */
15807|       |		if (setsockopt(so.sock,
15808|       |		               SOL_SOCKET,
15809|       |		               SO_EXCLUSIVEADDRUSE,
15810|       |		               (SOCK_OPT_TYPE)&on,
15811|       |		               sizeof(on))
15812|       |		    != 0) {
15813|       |
15814|       |			/* Set reuse option, but don't abort on errors. */
15815|       |			mg_cry_ctx_internal(
15816|       |			    phys_ctx,
15817|       |			    "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
15818|       |			    portsTotal);
15819|       |		}
15820|       |#else
15821|      1|		if (setsockopt(so.sock,
  ------------------
  |  Branch (15821:7): [True: 0, False: 1]
  ------------------
15822|      1|		               SOL_SOCKET,
15823|      1|		               SO_REUSEADDR,
15824|      1|		               (SOCK_OPT_TYPE)&on,
15825|      1|		               sizeof(on))
15826|      1|		    != 0) {
15827|       |
15828|       |			/* Set reuse option, but don't abort on errors. */
15829|      0|			mg_cry_ctx_internal(
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15830|      0|			    phys_ctx,
15831|      0|			    "cannot set socket option SO_REUSEADDR (entry %i)",
15832|      0|			    portsTotal);
15833|      0|		}
15834|      1|#endif
15835|       |
15836|       |#if defined(USE_X_DOM_SOCKET)
15837|       |		if (ip_version == 99) {
15838|       |			/* Unix domain socket */
15839|       |		} else
15840|       |#endif
15841|       |
15842|      1|		    if (ip_version > 4) {
  ------------------
  |  Branch (15842:11): [True: 0, False: 1]
  ------------------
15843|       |			/* Could be 6 for IPv6 onlyor 10 (4+6) for IPv4+IPv6 */
15844|       |#if defined(USE_IPV6)
15845|       |			if (ip_version > 6) {
15846|       |				if (so.lsa.sa.sa_family == AF_INET6
15847|       |				    && setsockopt(so.sock,
15848|       |				                  IPPROTO_IPV6,
15849|       |				                  IPV6_V6ONLY,
15850|       |				                  (void *)&off,
15851|       |				                  sizeof(off))
15852|       |				           != 0) {
15853|       |
15854|       |					/* Set IPv6 only option, but don't abort on errors. */
15855|       |					mg_cry_ctx_internal(phys_ctx,
15856|       |					                    "cannot set socket option "
15857|       |					                    "IPV6_V6ONLY=off (entry %i)",
15858|       |					                    portsTotal);
15859|       |				}
15860|       |			} else {
15861|       |				if (so.lsa.sa.sa_family == AF_INET6
15862|       |				    && setsockopt(so.sock,
15863|       |				                  IPPROTO_IPV6,
15864|       |				                  IPV6_V6ONLY,
15865|       |				                  (void *)&on,
15866|       |				                  sizeof(on))
15867|       |				           != 0) {
15868|       |
15869|       |					/* Set IPv6 only option, but don't abort on errors. */
15870|       |					mg_cry_ctx_internal(phys_ctx,
15871|       |					                    "cannot set socket option "
15872|       |					                    "IPV6_V6ONLY=on (entry %i)",
15873|       |					                    portsTotal);
15874|       |				}
15875|       |			}
15876|       |#else
15877|      0|			mg_cry_ctx_internal(phys_ctx, "%s", "IPv6 not available");
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15878|      0|			closesocket(so.sock);
  ------------------
  |  |  917|      0|#define closesocket(a) (close(a))
  ------------------
15879|      0|			so.sock = INVALID_SOCKET;
  ------------------
  |  |  925|      0|#define INVALID_SOCKET (-1)
  ------------------
15880|      0|			continue;
15881|      0|#endif
15882|      0|		}
15883|       |
15884|      1|		if (so.lsa.sa.sa_family == AF_INET) {
  ------------------
  |  Branch (15884:7): [True: 1, False: 0]
  ------------------
15885|       |
15886|      1|			len = sizeof(so.lsa.sin);
15887|      1|			if (bind(so.sock, &so.lsa.sa, len) != 0) {
  ------------------
  |  Branch (15887:8): [True: 0, False: 1]
  ------------------
15888|      0|				mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15889|      0|				                    "cannot bind to %.*s: %d (%s)",
15890|      0|				                    (int)vec.len,
15891|      0|				                    vec.ptr,
15892|      0|				                    (int)ERRNO,
15893|      0|				                    strerror(errno));
15894|      0|				closesocket(so.sock);
  ------------------
  |  |  917|      0|#define closesocket(a) (close(a))
  ------------------
15895|      0|				so.sock = INVALID_SOCKET;
  ------------------
  |  |  925|      0|#define INVALID_SOCKET (-1)
  ------------------
15896|      0|				continue;
15897|      0|			}
15898|      1|		}
15899|       |#if defined(USE_IPV6)
15900|       |		else if (so.lsa.sa.sa_family == AF_INET6) {
15901|       |
15902|       |			len = sizeof(so.lsa.sin6);
15903|       |			if (bind(so.sock, &so.lsa.sa, len) != 0) {
15904|       |				mg_cry_ctx_internal(phys_ctx,
15905|       |				                    "cannot bind to IPv6 %.*s: %d (%s)",
15906|       |				                    (int)vec.len,
15907|       |				                    vec.ptr,
15908|       |				                    (int)ERRNO,
15909|       |				                    strerror(errno));
15910|       |				closesocket(so.sock);
15911|       |				so.sock = INVALID_SOCKET;
15912|       |				continue;
15913|       |			}
15914|       |		}
15915|       |#endif
15916|       |#if defined(USE_X_DOM_SOCKET)
15917|       |		else if (so.lsa.sa.sa_family == AF_UNIX) {
15918|       |
15919|       |			len = sizeof(so.lsa.sun);
15920|       |			if (bind(so.sock, &so.lsa.sa, len) != 0) {
15921|       |				mg_cry_ctx_internal(phys_ctx,
15922|       |				                    "cannot bind to unix socket %s: %d (%s)",
15923|       |				                    so.lsa.sun.sun_path,
15924|       |				                    (int)ERRNO,
15925|       |				                    strerror(errno));
15926|       |				closesocket(so.sock);
15927|       |				so.sock = INVALID_SOCKET;
15928|       |				continue;
15929|       |			}
15930|       |		}
15931|       |#endif
15932|      0|		else {
15933|      0|			mg_cry_ctx_internal(
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15934|      0|			    phys_ctx,
15935|      0|			    "cannot bind: address family not supported (entry %i)",
15936|      0|			    portsTotal);
15937|      0|			closesocket(so.sock);
  ------------------
  |  |  917|      0|#define closesocket(a) (close(a))
  ------------------
15938|      0|			so.sock = INVALID_SOCKET;
  ------------------
  |  |  925|      0|#define INVALID_SOCKET (-1)
  ------------------
15939|      0|			continue;
15940|      0|		}
15941|       |
15942|      1|		opt_txt = phys_ctx->dd.config[LISTEN_BACKLOG_SIZE];
15943|      1|		opt_listen_backlog = strtol(opt_txt, NULL, 10);
15944|      1|		if ((opt_listen_backlog > INT_MAX) || (opt_listen_backlog < 1)) {
  ------------------
  |  Branch (15944:7): [True: 0, False: 1]
  |  Branch (15944:41): [True: 0, False: 1]
  ------------------
15945|      0|			mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15946|      0|			                    "%s value \"%s\" is invalid",
15947|      0|			                    config_options[LISTEN_BACKLOG_SIZE].name,
15948|      0|			                    opt_txt);
15949|      0|			closesocket(so.sock);
  ------------------
  |  |  917|      0|#define closesocket(a) (close(a))
  ------------------
15950|      0|			so.sock = INVALID_SOCKET;
  ------------------
  |  |  925|      0|#define INVALID_SOCKET (-1)
  ------------------
15951|      0|			continue;
15952|      0|		}
15953|       |
15954|      1|		if (listen(so.sock, (int)opt_listen_backlog) != 0) {
  ------------------
  |  Branch (15954:7): [True: 0, False: 1]
  ------------------
15955|       |
15956|      0|			mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15957|      0|			                    "cannot listen to %.*s: %d (%s)",
15958|      0|			                    (int)vec.len,
15959|      0|			                    vec.ptr,
15960|      0|			                    (int)ERRNO,
15961|      0|			                    strerror(errno));
15962|      0|			closesocket(so.sock);
  ------------------
  |  |  917|      0|#define closesocket(a) (close(a))
  ------------------
15963|      0|			so.sock = INVALID_SOCKET;
  ------------------
  |  |  925|      0|#define INVALID_SOCKET (-1)
  ------------------
15964|      0|			continue;
15965|      0|		}
15966|       |
15967|      1|		if ((getsockname(so.sock, &(usa.sa), &len) != 0)
  ------------------
  |  Branch (15967:7): [True: 0, False: 1]
  ------------------
15968|      1|		    || (usa.sa.sa_family != so.lsa.sa.sa_family)) {
  ------------------
  |  Branch (15968:10): [True: 0, False: 1]
  ------------------
15969|       |
15970|      0|			int err = (int)ERRNO;
  ------------------
  |  |  924|      0|#define ERRNO (errno)
  ------------------
15971|      0|			mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
15972|      0|			                    "call to getsockname failed %.*s: %d (%s)",
15973|      0|			                    (int)vec.len,
15974|      0|			                    vec.ptr,
15975|      0|			                    err,
15976|      0|			                    strerror(errno));
15977|      0|			closesocket(so.sock);
  ------------------
  |  |  917|      0|#define closesocket(a) (close(a))
  ------------------
15978|      0|			so.sock = INVALID_SOCKET;
  ------------------
  |  |  925|      0|#define INVALID_SOCKET (-1)
  ------------------
15979|      0|			continue;
15980|      0|		}
15981|       |
15982|       |		/* Update lsa port in case of random free ports */
15983|       |#if defined(USE_IPV6)
15984|       |		if (so.lsa.sa.sa_family == AF_INET6) {
15985|       |			so.lsa.sin6.sin6_port = usa.sin6.sin6_port;
15986|       |		} else
15987|       |#endif
15988|      1|		{
15989|      1|			so.lsa.sin.sin_port = usa.sin.sin_port;
15990|      1|		}
15991|       |
15992|      1|		if ((ptr = (struct socket *)
  ------------------
  |  Branch (15992:7): [True: 0, False: 1]
  ------------------
15993|      1|		         mg_realloc_ctx(phys_ctx->listening_sockets,
  ------------------
  |  | 1499|      1|#define mg_realloc_ctx(a, b, c) mg_realloc(a, b)
  ------------------
15994|      1|		                        (phys_ctx->num_listening_sockets + 1)
15995|      1|		                            * sizeof(phys_ctx->listening_sockets[0]),
15996|      1|		                        phys_ctx))
15997|      1|		    == NULL) {
15998|       |
15999|      0|			mg_cry_ctx_internal(phys_ctx, "%s", "Out of memory");
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
16000|      0|			closesocket(so.sock);
  ------------------
  |  |  917|      0|#define closesocket(a) (close(a))
  ------------------
16001|      0|			so.sock = INVALID_SOCKET;
  ------------------
  |  |  925|      0|#define INVALID_SOCKET (-1)
  ------------------
16002|      0|			continue;
16003|      0|		}
16004|       |
16005|      1|		if ((pfd = (struct mg_pollfd *)
  ------------------
  |  Branch (16005:7): [True: 0, False: 1]
  ------------------
16006|      1|		         mg_realloc_ctx(phys_ctx->listening_socket_fds,
  ------------------
  |  | 1499|      1|#define mg_realloc_ctx(a, b, c) mg_realloc(a, b)
  ------------------
16007|      1|		                        (phys_ctx->num_listening_sockets + 1)
16008|      1|		                            * sizeof(phys_ctx->listening_socket_fds[0]),
16009|      1|		                        phys_ctx))
16010|      1|		    == NULL) {
16011|       |
16012|      0|			mg_cry_ctx_internal(phys_ctx, "%s", "Out of memory");
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
16013|      0|			closesocket(so.sock);
  ------------------
  |  |  917|      0|#define closesocket(a) (close(a))
  ------------------
16014|      0|			so.sock = INVALID_SOCKET;
  ------------------
  |  |  925|      0|#define INVALID_SOCKET (-1)
  ------------------
16015|      0|			mg_free(ptr);
16016|      0|			continue;
16017|      0|		}
16018|       |
16019|      1|		set_close_on_exec(so.sock, NULL, phys_ctx);
16020|      1|		phys_ctx->listening_sockets = ptr;
16021|      1|		phys_ctx->listening_sockets[phys_ctx->num_listening_sockets] = so;
16022|      1|		phys_ctx->listening_socket_fds = pfd;
16023|      1|		phys_ctx->num_listening_sockets++;
16024|      1|		portsOk++;
16025|      1|	}
16026|       |
16027|      1|	if (portsOk != portsTotal) {
  ------------------
  |  Branch (16027:6): [True: 0, False: 1]
  ------------------
16028|      0|		close_all_listening_sockets(phys_ctx);
16029|      0|		portsOk = 0;
16030|      0|	}
16031|       |
16032|      1|	return portsOk;
16033|      1|}
civetweb.c:parse_port_string:
15493|      1|{
15494|      1|	unsigned int a, b, c, d;
15495|      1|	unsigned port;
15496|      1|	unsigned long portUL;
15497|      1|	int ch, len;
15498|      1|	const char *cb;
15499|      1|	char *endptr;
15500|       |#if defined(USE_IPV6)
15501|       |	char buf[100] = {0};
15502|       |#endif
15503|       |
15504|       |	/* MacOS needs that. If we do not zero it, subsequent bind() will fail.
15505|       |	 * Also, all-zeroes in the socket address means binding to all addresses
15506|       |	 * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
15507|      1|	memset(so, 0, sizeof(*so));
15508|      1|	so->lsa.sin.sin_family = AF_INET;
15509|      1|	*ip_version = 0;
15510|       |
15511|       |	/* Initialize len as invalid. */
15512|      1|	port = 0;
15513|      1|	len = 0;
15514|       |
15515|       |	/* Test for different ways to format this string */
15516|      1|	if (sscanf(vec->ptr,
  ------------------
  |  Branch (15516:6): [True: 0, False: 1]
  ------------------
15517|      1|	           "%u.%u.%u.%u:%u%n",
15518|      1|	           &a,
15519|      1|	           &b,
15520|      1|	           &c,
15521|      1|	           &d,
15522|      1|	           &port,
15523|      1|	           &len) // NOLINT(cert-err34-c) 'sscanf' used to convert a string
15524|       |	                 // to an integer value, but function will not report
15525|       |	                 // conversion errors; consider using 'strtol' instead
15526|      1|	    == 5) {
15527|       |		/* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
15528|      0|		so->lsa.sin.sin_addr.s_addr =
15529|      0|		    htonl((a << 24) | (b << 16) | (c << 8) | d);
15530|      0|		so->lsa.sin.sin_port = htons((uint16_t)port);
15531|      0|		*ip_version = 4;
15532|       |
15533|       |#if defined(USE_IPV6)
15534|       |	} else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
15535|       |	           && ((size_t)len <= vec->len)
15536|       |	           && mg_inet_pton(
15537|       |	                  AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6), 0)) {
15538|       |		/* IPv6 address, examples: see above */
15539|       |		/* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
15540|       |		 */
15541|       |		so->lsa.sin6.sin6_port = htons((uint16_t)port);
15542|       |		*ip_version = 6;
15543|       |#endif
15544|       |
15545|      1|	} else if ((vec->ptr[0] == '+')
  ------------------
  |  Branch (15545:13): [True: 0, False: 1]
  ------------------
15546|      1|	           && (sscanf(vec->ptr + 1, "%u%n", &port, &len)
  ------------------
  |  Branch (15546:16): [True: 0, False: 0]
  ------------------
15547|      0|	               == 1)) { // NOLINT(cert-err34-c) 'sscanf' used to convert a
15548|       |		                    // string to an integer value, but function will not
15549|       |		                    // report conversion errors; consider using 'strtol'
15550|       |		                    // instead
15551|       |
15552|       |		/* Port is specified with a +, bind to IPv6 and IPv4, INADDR_ANY */
15553|       |		/* Add 1 to len for the + character we skipped before */
15554|      0|		len++;
15555|       |
15556|       |#if defined(USE_IPV6)
15557|       |		/* Set socket family to IPv6, do not use IPV6_V6ONLY */
15558|       |		so->lsa.sin6.sin6_family = AF_INET6;
15559|       |		so->lsa.sin6.sin6_port = htons((uint16_t)port);
15560|       |		*ip_version = 4 + 6;
15561|       |#else
15562|       |		/* Bind to IPv4 only, since IPv6 is not built in. */
15563|      0|		so->lsa.sin.sin_port = htons((uint16_t)port);
15564|      0|		*ip_version = 4;
15565|      0|#endif
15566|       |
15567|      1|	} else if (is_valid_port(portUL = strtoul(vec->ptr, &endptr, 0))
  ------------------
  |  Branch (15567:13): [True: 1, False: 0]
  ------------------
15568|      1|	           && (vec->ptr != endptr)) {
  ------------------
  |  Branch (15568:16): [True: 1, False: 0]
  ------------------
15569|      1|		len = (int)(endptr - vec->ptr);
15570|      1|		port = (uint16_t)portUL;
15571|       |		/* If only port is specified, bind to IPv4, INADDR_ANY */
15572|      1|		so->lsa.sin.sin_port = htons((uint16_t)port);
15573|      1|		*ip_version = 4;
15574|       |
15575|      1|	} else if ((cb = strchr(vec->ptr, ':')) != NULL) {
  ------------------
  |  Branch (15575:13): [True: 0, False: 0]
  ------------------
15576|       |		/* String could be a hostname. This check algorithm
15577|       |		 * will only work for RFC 952 compliant hostnames,
15578|       |		 * starting with a letter, containing only letters,
15579|       |		 * digits and hyphen ('-'). Newer specs may allow
15580|       |		 * more, but this is not guaranteed here, since it
15581|       |		 * may interfere with rules for port option lists. */
15582|       |
15583|       |		/* According to RFC 1035, hostnames are restricted to 255 characters
15584|       |		 * in total (63 between two dots). */
15585|      0|		char hostname[256];
15586|      0|		size_t hostnlen = (size_t)(cb - vec->ptr);
15587|       |
15588|      0|		if ((hostnlen >= vec->len) || (hostnlen >= sizeof(hostname))) {
  ------------------
  |  Branch (15588:7): [True: 0, False: 0]
  |  Branch (15588:33): [True: 0, False: 0]
  ------------------
15589|       |			/* This would be invalid in any case */
15590|      0|			*ip_version = 0;
15591|      0|			return 0;
15592|      0|		}
15593|       |
15594|      0|		mg_strlcpy(hostname, vec->ptr, hostnlen + 1);
15595|       |
15596|      0|		if (mg_inet_pton(
  ------------------
  |  Branch (15596:7): [True: 0, False: 0]
  ------------------
15597|      0|		        AF_INET, hostname, &so->lsa.sin, sizeof(so->lsa.sin), 1)) {
15598|      0|			if (sscanf(cb + 1, "%u%n", &port, &len)
  ------------------
  |  Branch (15598:8): [True: 0, False: 0]
  ------------------
15599|      0|			    == 1) { // NOLINT(cert-err34-c) 'sscanf' used to convert a
15600|       |				        // string to an integer value, but function will not
15601|       |				        // report conversion errors; consider using 'strtol'
15602|       |				        // instead
15603|      0|				*ip_version = 4;
15604|      0|				so->lsa.sin.sin_port = htons((uint16_t)port);
15605|      0|				len += (int)(hostnlen + 1);
15606|      0|			} else {
15607|      0|				len = 0;
15608|      0|			}
15609|       |#if defined(USE_IPV6)
15610|       |		} else if (mg_inet_pton(AF_INET6,
15611|       |		                        hostname,
15612|       |		                        &so->lsa.sin6,
15613|       |		                        sizeof(so->lsa.sin6),
15614|       |		                        1)) {
15615|       |			if (sscanf(cb + 1, "%u%n", &port, &len) == 1) {
15616|       |				*ip_version = 6;
15617|       |				so->lsa.sin6.sin6_port = htons((uint16_t)port);
15618|       |				len += (int)(hostnlen + 1);
15619|       |			} else {
15620|       |				len = 0;
15621|       |			}
15622|       |#endif
15623|      0|		} else {
15624|      0|			len = 0;
15625|      0|		}
15626|       |
15627|       |#if defined(USE_X_DOM_SOCKET)
15628|       |
15629|       |	} else if (vec->ptr[0] == 'x') {
15630|       |		/* unix (linux) domain socket */
15631|       |		if (vec->len < sizeof(so->lsa.sun.sun_path)) {
15632|       |			len = vec->len;
15633|       |			so->lsa.sun.sun_family = AF_UNIX;
15634|       |			memset(so->lsa.sun.sun_path, 0, sizeof(so->lsa.sun.sun_path));
15635|       |			memcpy(so->lsa.sun.sun_path, (char *)vec->ptr + 1, vec->len - 1);
15636|       |			port = 0;
15637|       |			*ip_version = 99;
15638|       |		} else {
15639|       |			/* String too long */
15640|       |			len = 0;
15641|       |		}
15642|       |#endif
15643|       |
15644|      0|	} else {
15645|       |		/* Parsing failure. */
15646|      0|		len = 0;
15647|      0|	}
15648|       |
15649|       |	/* sscanf and the option splitting code ensure the following condition
15650|       |	 * Make sure the port is valid and vector ends with the port, 's' or 'r' */
15651|      1|	if ((len > 0) && is_valid_port(port)
  ------------------
  |  Branch (15651:6): [True: 1, False: 0]
  |  Branch (15651:19): [True: 1, False: 0]
  ------------------
15652|      1|	    && (((size_t)len == vec->len) || (((size_t)len + 1) == vec->len))) {
  ------------------
  |  Branch (15652:10): [True: 1, False: 0]
  |  Branch (15652:39): [True: 0, False: 0]
  ------------------
15653|       |		/* Next character after the port number */
15654|      1|		ch = ((size_t)len < vec->len) ? vec->ptr[len] : '\0';
  ------------------
  |  Branch (15654:8): [True: 0, False: 1]
  ------------------
15655|      1|		so->is_ssl = (ch == 's');
15656|      1|		so->ssl_redir = (ch == 'r');
15657|      1|		if ((ch == '\0') || (ch == 's') || (ch == 'r')) {
  ------------------
  |  Branch (15657:7): [True: 1, False: 0]
  |  Branch (15657:23): [True: 0, False: 0]
  |  Branch (15657:38): [True: 0, False: 0]
  ------------------
15658|      1|			return 1;
15659|      1|		}
15660|      1|	}
15661|       |
15662|       |	/* Reset ip_version to 0 if there is an error */
15663|      0|	*ip_version = 0;
15664|      0|	return 0;
15665|      1|}
civetweb.c:close_all_listening_sockets:
15448|      1|{
15449|      1|	unsigned int i;
15450|      1|	if (!ctx) {
  ------------------
  |  Branch (15450:6): [True: 0, False: 1]
  ------------------
15451|      0|		return;
15452|      0|	}
15453|       |
15454|      2|	for (i = 0; i < ctx->num_listening_sockets; i++) {
  ------------------
  |  Branch (15454:14): [True: 1, False: 1]
  ------------------
15455|      1|		closesocket(ctx->listening_sockets[i].sock);
  ------------------
  |  |  917|      1|#define closesocket(a) (close(a))
  ------------------
15456|       |#if defined(USE_X_DOM_SOCKET)
15457|       |		/* For unix domain sockets, the socket name represents a file that has
15458|       |		 * to be deleted. */
15459|       |		/* See
15460|       |		 * https://stackoverflow.com/questions/15716302/so-reuseaddr-and-af-unix
15461|       |		 */
15462|       |		if ((ctx->listening_sockets[i].lsa.sin.sin_family == AF_UNIX)
15463|       |		    && (ctx->listening_sockets[i].sock != INVALID_SOCKET)) {
15464|       |			IGNORE_UNUSED_RESULT(
15465|       |			    remove(ctx->listening_sockets[i].lsa.sun.sun_path));
15466|       |		}
15467|       |#endif
15468|      1|		ctx->listening_sockets[i].sock = INVALID_SOCKET;
  ------------------
  |  |  925|      1|#define INVALID_SOCKET (-1)
  ------------------
15469|      1|	}
15470|      1|	mg_free(ctx->listening_sockets);
15471|      1|	ctx->listening_sockets = NULL;
15472|      1|	mg_free(ctx->listening_socket_fds);
15473|      1|	ctx->listening_socket_fds = NULL;
15474|      1|}
civetweb.c:set_uid_option:
16259|      1|{
16260|      1|	int success = 0;
16261|       |
16262|      1|	if (phys_ctx) {
  ------------------
  |  Branch (16262:6): [True: 1, False: 0]
  ------------------
16263|       |		/* We are currently running as curr_uid. */
16264|      1|		const uid_t curr_uid = getuid();
16265|       |		/* If set, we want to run as run_as_user. */
16266|      1|		const char *run_as_user = phys_ctx->dd.config[RUN_AS_USER];
16267|      1|		const struct passwd *to_pw = NULL;
16268|       |
16269|      1|		if ((run_as_user != NULL) && (to_pw = getpwnam(run_as_user)) == NULL) {
  ------------------
  |  Branch (16269:7): [True: 0, False: 1]
  |  Branch (16269:32): [True: 0, False: 0]
  ------------------
16270|       |			/* run_as_user does not exist on the system. We can't proceed
16271|       |			 * further. */
16272|      0|			mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
16273|      0|			                    "%s: unknown user [%s]",
16274|      0|			                    __func__,
16275|      0|			                    run_as_user);
16276|      1|		} else if ((run_as_user == NULL) || (curr_uid == to_pw->pw_uid)) {
  ------------------
  |  Branch (16276:14): [True: 1, False: 0]
  |  Branch (16276:39): [True: 0, False: 0]
  ------------------
16277|       |			/* There was either no request to change user, or we're already
16278|       |			 * running as run_as_user. Nothing else to do.
16279|       |			 */
16280|      1|			success = 1;
16281|      1|		} else {
16282|       |			/* Valid change request.  */
16283|      0|			if (setgid(to_pw->pw_gid) == -1) {
  ------------------
  |  Branch (16283:8): [True: 0, False: 0]
  ------------------
16284|      0|				mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
16285|      0|				                    "%s: setgid(%s): %s",
16286|      0|				                    __func__,
16287|      0|				                    run_as_user,
16288|      0|				                    strerror(errno));
16289|      0|			} else if (setgroups(0, NULL) == -1) {
  ------------------
  |  Branch (16289:15): [True: 0, False: 0]
  ------------------
16290|      0|				mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
16291|      0|				                    "%s: setgroups(): %s",
16292|      0|				                    __func__,
16293|      0|				                    strerror(errno));
16294|      0|			} else if (setuid(to_pw->pw_uid) == -1) {
  ------------------
  |  Branch (16294:15): [True: 0, False: 0]
  ------------------
16295|      0|				mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
16296|      0|				                    "%s: setuid(%s): %s",
16297|      0|				                    __func__,
16298|      0|				                    run_as_user,
16299|      0|				                    strerror(errno));
16300|      0|			} else {
16301|      0|				success = 1;
16302|      0|			}
16303|      0|		}
16304|      1|	}
16305|       |
16306|      1|	return success;
16307|      1|}
civetweb.c:set_acl_option:
17654|      1|{
17655|      1|	union usa sa;
17656|      1|	memset(&sa, 0, sizeof(sa));
17657|       |#if defined(USE_IPV6)
17658|       |	sa.sin6.sin6_family = AF_INET6;
17659|       |#else
17660|      1|	sa.sin.sin_family = AF_INET;
17661|      1|#endif
17662|      1|	return check_acl(phys_ctx, &sa) != -1;
17663|      1|}
civetweb.c:check_acl:
16221|      1|{
16222|      1|	int allowed, flag, matched;
16223|      1|	struct vec vec;
16224|       |
16225|      1|	if (phys_ctx) {
  ------------------
  |  Branch (16225:6): [True: 1, False: 0]
  ------------------
16226|      1|		const char *list = phys_ctx->dd.config[ACCESS_CONTROL_LIST];
16227|       |
16228|       |		/* If any ACL is set, deny by default */
16229|      1|		allowed = (list == NULL) ? '+' : '-';
  ------------------
  |  Branch (16229:13): [True: 1, False: 0]
  ------------------
16230|       |
16231|      1|		while ((list = next_option(list, &vec, NULL)) != NULL) {
  ------------------
  |  Branch (16231:10): [True: 0, False: 1]
  ------------------
16232|      0|			flag = vec.ptr[0];
16233|      0|			matched = -1;
16234|      0|			if ((vec.len > 0) && ((flag == '+') || (flag == '-'))) {
  ------------------
  |  Branch (16234:8): [True: 0, False: 0]
  |  Branch (16234:26): [True: 0, False: 0]
  |  Branch (16234:43): [True: 0, False: 0]
  ------------------
16235|      0|				vec.ptr++;
16236|      0|				vec.len--;
16237|      0|				matched = parse_match_net(&vec, sa, 1);
16238|      0|			}
16239|      0|			if (matched < 0) {
  ------------------
  |  Branch (16239:8): [True: 0, False: 0]
  ------------------
16240|      0|				mg_cry_ctx_internal(phys_ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
16241|      0|				                    "%s: subnet must be [+|-]IP-addr[/x]",
16242|      0|				                    __func__);
16243|      0|				return -1;
16244|      0|			}
16245|      0|			if (matched) {
  ------------------
  |  Branch (16245:8): [True: 0, False: 0]
  ------------------
16246|      0|				allowed = flag;
16247|      0|			}
16248|      0|		}
16249|       |
16250|      1|		return allowed == '+';
16251|      1|	}
16252|      0|	return -1;
16253|      1|}
civetweb.c:mg_start_thread_with_id:
 5729|     51|{
 5730|     51|	pthread_t thread_id;
 5731|     51|	pthread_attr_t attr;
 5732|     51|	int result;
 5733|       |
 5734|     51|	(void)pthread_attr_init(&attr);
 5735|       |
 5736|       |#if defined(__ZEPHYR__)
 5737|       |	pthread_attr_setstack(&attr,
 5738|       |	                      &civetweb_worker_stacks[zephyr_worker_stack_index++],
 5739|       |	                      ZEPHYR_STACK_SIZE);
 5740|       |#elif defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
 5741|       |	/* Compile-time option to control stack size,
 5742|       |	 * e.g. -DUSE_STACK_SIZE=16384 */
 5743|     51|	(void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
 5744|     51|#endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
 5745|       |
 5746|     51|	result = pthread_create(&thread_id, &attr, func, param);
 5747|     51|	pthread_attr_destroy(&attr);
 5748|     51|	if ((result == 0) && (threadidptr != NULL)) {
  ------------------
  |  Branch (5748:6): [True: 51, False: 0]
  |  Branch (5748:23): [True: 51, False: 0]
  ------------------
 5749|     51|		*threadidptr = thread_id;
 5750|     51|	}
 5751|     51|	return result;
 5752|     51|}
civetweb.c:worker_thread:
19929|     50|{
19930|     50|#if !defined(__ZEPHYR__)
19931|     50|	struct sigaction sa;
19932|       |
19933|       |	/* Ignore SIGPIPE */
19934|     50|	memset(&sa, 0, sizeof(sa));
19935|     50|	sa.sa_handler = SIG_IGN;
19936|     50|	sigaction(SIGPIPE, &sa, NULL);
19937|     50|#endif
19938|       |
19939|     50|	worker_thread_run((struct mg_connection *)thread_func_param);
19940|     50|	return NULL;
19941|     50|}
civetweb.c:worker_thread_run:
19696|     50|{
19697|     50|	struct mg_context *ctx = conn->phys_ctx;
19698|     50|	int thread_index;
19699|     50|	struct mg_workerTLS tls;
19700|       |
19701|     50|	mg_set_thread_name("worker");
19702|       |
19703|     50|	tls.is_master = 0;
19704|     50|	tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
19705|       |#if defined(_WIN32)
19706|       |	tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
19707|       |#endif
19708|       |
19709|       |	/* Initialize thread local storage before calling any callback */
19710|     50|	pthread_setspecific(sTlsKey, &tls);
19711|       |
19712|       |	/* Check if there is a user callback */
19713|     50|	if (ctx->callbacks.init_thread) {
  ------------------
  |  Branch (19713:6): [True: 0, False: 50]
  ------------------
19714|       |		/* call init_thread for a worker thread (type 1), and store the
19715|       |		 * return value */
19716|      0|		tls.user_ptr = ctx->callbacks.init_thread(ctx, 1);
19717|     50|	} else {
19718|       |		/* No callback: set user pointer to NULL */
19719|     50|		tls.user_ptr = NULL;
19720|     50|	}
19721|       |
19722|       |	/* Connection structure has been pre-allocated */
19723|     50|	thread_index = (int)(conn - ctx->worker_connections);
19724|     50|	if ((thread_index < 0)
  ------------------
  |  Branch (19724:6): [True: 0, False: 50]
  ------------------
19725|     50|	    || ((unsigned)thread_index >= (unsigned)ctx->cfg_worker_threads)) {
  ------------------
  |  Branch (19725:9): [True: 0, False: 50]
  ------------------
19726|      0|		mg_cry_ctx_internal(ctx,
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
19727|      0|		                    "Internal error: Invalid worker index %i",
19728|      0|		                    thread_index);
19729|      0|		return;
19730|      0|	}
19731|       |
19732|       |	/* Request buffers are not pre-allocated. They are private to the
19733|       |	 * request and do not contain any state information that might be
19734|       |	 * of interest to anyone observing a server status.  */
19735|     50|	conn->buf = (char *)mg_malloc_ctx(ctx->max_request_size, conn->phys_ctx);
  ------------------
  |  | 1497|     50|#define mg_malloc_ctx(a, c) mg_malloc(a)
  ------------------
19736|     50|	if (conn->buf == NULL) {
  ------------------
  |  Branch (19736:6): [True: 0, False: 50]
  ------------------
19737|      0|		mg_cry_ctx_internal(
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
19738|      0|		    ctx,
19739|      0|		    "Out of memory: Cannot allocate buffer for worker %i",
19740|      0|		    thread_index);
19741|      0|		return;
19742|      0|	}
19743|     50|	conn->buf_size = (int)ctx->max_request_size;
19744|       |
19745|     50|	conn->dom_ctx = &(ctx->dd); /* Use default domain and default host */
19746|       |
19747|     50|	conn->tls_user_ptr = tls.user_ptr; /* store ptr for quick access */
19748|       |
19749|     50|	conn->request_info.user_data = ctx->user_data;
19750|       |	/* Allocate a mutex for this connection to allow communication both
19751|       |	 * within the request handler and from elsewhere in the application
19752|       |	 */
19753|     50|	if (0 != pthread_mutex_init(&conn->mutex, &pthread_mutex_attr)) {
  ------------------
  |  Branch (19753:6): [True: 0, False: 50]
  ------------------
19754|      0|		mg_free(conn->buf);
19755|      0|		mg_cry_ctx_internal(ctx, "%s", "Cannot create mutex");
  ------------------
  |  | 2587|      0|	mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
  ------------------
19756|      0|		return;
19757|      0|	}
19758|       |
19759|       |#if defined(USE_SERVER_STATS)
19760|       |	conn->conn_state = 1; /* not consumed */
19761|       |#endif
19762|       |
19763|       |	/* Call consume_socket() even when ctx->stop_flag > 0, to let it
19764|       |	 * signal sq_empty condvar to wake up the master waiting in
19765|       |	 * produce_socket() */
19766|     50|	while (consume_socket(ctx, &conn->client, thread_index)) {
  ------------------
  |  Branch (19766:9): [True: 0, False: 50]
  ------------------
19767|       |
19768|       |		/* New connections must start with new protocol negotiation */
19769|      0|		tls.alpn_proto = NULL;
19770|       |
19771|       |#if defined(USE_SERVER_STATS)
19772|       |		conn->conn_close_time = 0;
19773|       |#endif
19774|      0|		conn->conn_birth_time = time(NULL);
19775|       |
19776|       |		/* Fill in IP, port info early so even if SSL setup below fails,
19777|       |		 * error handler would have the corresponding info.
19778|       |		 * Thanks to Johannes Winkelmann for the patch.
19779|       |		 */
19780|      0|		conn->request_info.remote_port =
19781|      0|		    ntohs(USA_IN_PORT_UNSAFE(&conn->client.rsa));
19782|       |
19783|      0|		conn->request_info.server_port =
19784|      0|		    ntohs(USA_IN_PORT_UNSAFE(&conn->client.lsa));
19785|       |
19786|      0|		sockaddr_to_string(conn->request_info.remote_addr,
19787|      0|		                   sizeof(conn->request_info.remote_addr),
19788|      0|		                   &conn->client.rsa);
19789|       |
19790|      0|		DEBUG_TRACE("Incoming %sconnection from %s",
  ------------------
  |  |  243|      0|	do {                                                                       \
  |  |  244|      0|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
19791|      0|		            (conn->client.is_ssl ? "SSL " : ""),
19792|      0|		            conn->request_info.remote_addr);
19793|       |
19794|      0|		conn->request_info.is_ssl = conn->client.is_ssl;
19795|       |
19796|      0|		if (conn->client.is_ssl) {
  ------------------
  |  Branch (19796:7): [True: 0, False: 0]
  ------------------
19797|       |
19798|       |#if defined(USE_MBEDTLS)
19799|       |			/* HTTPS connection */
19800|       |			if (mbed_ssl_accept(&(conn->ssl),
19801|       |			                    conn->dom_ctx->ssl_ctx,
19802|       |			                    (int *)&(conn->client.sock),
19803|       |			                    conn->phys_ctx)
19804|       |			    == 0) {
19805|       |				/* conn->dom_ctx is set in get_request */
19806|       |				/* process HTTPS connection */
19807|       |				init_connection(conn);
19808|       |				conn->connection_type = CONNECTION_TYPE_REQUEST;
19809|       |				conn->protocol_type = PROTOCOL_TYPE_HTTP1;
19810|       |				process_new_connection(conn);
19811|       |			} else {
19812|       |				/* make sure the connection is cleaned up on SSL failure */
19813|       |				close_connection(conn);
19814|       |			}
19815|       |
19816|       |#elif !defined(NO_SSL)
19817|       |			/* HTTPS connection */
19818|      0|			if (sslize(conn, SSL_accept, NULL)) {
  ------------------
  |  |  105|      0|#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
  ------------------
  |  Branch (19818:8): [True: 0, False: 0]
  ------------------
19819|       |				/* conn->dom_ctx is set in get_request */
19820|       |
19821|       |				/* Get SSL client certificate information (if set) */
19822|      0|				struct mg_client_cert client_cert;
19823|      0|				if (ssl_get_client_cert_info(conn, &client_cert)) {
  ------------------
  |  Branch (19823:9): [True: 0, False: 0]
  ------------------
19824|      0|					conn->request_info.client_cert = &client_cert;
19825|      0|				}
19826|       |
19827|       |				/* process HTTPS connection */
19828|       |#if defined(USE_HTTP2)
19829|       |				if ((tls.alpn_proto != NULL)
19830|       |				    && (!memcmp(tls.alpn_proto, "\x02h2", 3))) {
19831|       |					/* process HTTPS/2 connection */
19832|       |					init_connection(conn);
19833|       |					conn->connection_type = CONNECTION_TYPE_REQUEST;
19834|       |					conn->protocol_type = PROTOCOL_TYPE_HTTP2;
19835|       |					conn->content_len =
19836|       |					    -1;               /* content length is not predefined */
19837|       |					conn->is_chunked = 0; /* HTTP2 is never chunked */
19838|       |					process_new_http2_connection(conn);
19839|       |				} else
19840|       |#endif
19841|      0|				{
19842|       |					/* process HTTPS/1.x or WEBSOCKET-SECURE connection */
19843|      0|					init_connection(conn);
19844|      0|					conn->connection_type = CONNECTION_TYPE_REQUEST;
19845|       |					/* Start with HTTP, WS will be an "upgrade" request later */
19846|      0|					conn->protocol_type = PROTOCOL_TYPE_HTTP1;
19847|      0|					process_new_connection(conn);
19848|      0|				}
19849|       |
19850|       |				/* Free client certificate info */
19851|      0|				if (conn->request_info.client_cert) {
  ------------------
  |  Branch (19851:9): [True: 0, False: 0]
  ------------------
19852|      0|					mg_free((void *)(conn->request_info.client_cert->subject));
19853|      0|					mg_free((void *)(conn->request_info.client_cert->issuer));
19854|      0|					mg_free((void *)(conn->request_info.client_cert->serial));
19855|      0|					mg_free((void *)(conn->request_info.client_cert->finger));
19856|       |					/* Free certificate memory */
19857|      0|					X509_free(
  ------------------
  |  |  213|      0|#define X509_free (*(void (*)(X509 *))crypto_sw[3].ptr)
  ------------------
19858|      0|					    (X509 *)conn->request_info.client_cert->peer_cert);
19859|      0|					conn->request_info.client_cert->peer_cert = 0;
19860|      0|					conn->request_info.client_cert->subject = 0;
19861|      0|					conn->request_info.client_cert->issuer = 0;
19862|      0|					conn->request_info.client_cert->serial = 0;
19863|      0|					conn->request_info.client_cert->finger = 0;
19864|      0|					conn->request_info.client_cert = 0;
19865|      0|				}
19866|      0|			} else {
19867|       |				/* make sure the connection is cleaned up on SSL failure */
19868|      0|				close_connection(conn);
19869|      0|			}
19870|      0|#endif
19871|       |
19872|      0|		} else {
19873|       |			/* process HTTP connection */
19874|      0|			init_connection(conn);
19875|      0|			conn->connection_type = CONNECTION_TYPE_REQUEST;
19876|       |			/* Start with HTTP, WS will be an "upgrade" request later */
19877|      0|			conn->protocol_type = PROTOCOL_TYPE_HTTP1;
19878|      0|			process_new_connection(conn);
19879|      0|		}
19880|       |
19881|      0|		DEBUG_TRACE("%s", "Connection closed");
  ------------------
  |  |  243|      0|	do {                                                                       \
  |  |  244|      0|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
19882|       |
19883|       |#if defined(USE_SERVER_STATS)
19884|       |		conn->conn_close_time = time(NULL);
19885|       |#endif
19886|      0|	}
19887|       |
19888|       |	/* Call exit thread user callback */
19889|     50|	if (ctx->callbacks.exit_thread) {
  ------------------
  |  Branch (19889:6): [True: 0, False: 50]
  ------------------
19890|      0|		ctx->callbacks.exit_thread(ctx, 1, tls.user_ptr);
19891|      0|	}
19892|       |
19893|       |	/* delete thread local storage objects */
19894|     50|	pthread_setspecific(sTlsKey, NULL);
19895|       |#if defined(_WIN32)
19896|       |	CloseHandle(tls.pthread_cond_helper_mutex);
19897|       |#endif
19898|     50|	pthread_mutex_destroy(&conn->mutex);
19899|       |
19900|       |	/* Free the request buffer. */
19901|     50|	conn->buf_size = 0;
19902|     50|	mg_free(conn->buf);
19903|     50|	conn->buf = NULL;
19904|       |
19905|       |	/* Free cleaned URI (if any) */
19906|     50|	if (conn->request_info.local_uri != conn->request_info.local_uri_raw) {
  ------------------
  |  Branch (19906:6): [True: 0, False: 50]
  ------------------
19907|      0|		mg_free((void *)conn->request_info.local_uri);
19908|      0|		conn->request_info.local_uri = NULL;
19909|      0|	}
19910|       |
19911|       |#if defined(USE_SERVER_STATS)
19912|       |	conn->conn_state = 9; /* done */
19913|       |#endif
19914|       |
19915|     50|	DEBUG_TRACE("%s", "exiting");
  ------------------
  |  |  243|     50|	do {                                                                       \
  |  |  244|     50|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
19916|     50|}
civetweb.c:mg_set_thread_name:
 2781|     51|{
 2782|     51|	char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
 2783|       |
 2784|     51|	mg_snprintf(
 2785|     51|	    NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
 2786|       |
 2787|       |#if defined(_WIN32)
 2788|       |#if defined(_MSC_VER)
 2789|       |	/* Windows and Visual Studio Compiler */
 2790|       |	__try {
 2791|       |		THREADNAME_INFO info;
 2792|       |		info.dwType = 0x1000;
 2793|       |		info.szName = threadName;
 2794|       |		info.dwThreadID = ~0U;
 2795|       |		info.dwFlags = 0;
 2796|       |
 2797|       |		RaiseException(0x406D1388,
 2798|       |		               0,
 2799|       |		               sizeof(info) / sizeof(ULONG_PTR),
 2800|       |		               (ULONG_PTR *)&info);
 2801|       |	} __except (EXCEPTION_EXECUTE_HANDLER) {
 2802|       |	}
 2803|       |#elif defined(__MINGW32__)
 2804|       |	/* No option known to set thread name for MinGW known */
 2805|       |#endif
 2806|       |#elif defined(_GNU_SOURCE) && defined(__GLIBC__)                               \
 2807|       |    && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
 2808|       |	/* pthread_setname_np first appeared in glibc in version 2.12 */
 2809|       |#if defined(__MACH__) && defined(__APPLE__)
 2810|       |	/* OS X only current thread name can be changed */
 2811|       |	(void)pthread_setname_np(threadName);
 2812|       |#else
 2813|     51|	(void)pthread_setname_np(pthread_self(), threadName);
 2814|     51|#endif
 2815|       |#elif defined(__linux__)
 2816|       |	/* On Linux we can use the prctl function.
 2817|       |	 * When building for Linux Standard Base (LSB) use
 2818|       |	 * NO_THREAD_NAME. However, thread names are a big
 2819|       |	 * help for debugging, so the stadard is to set them.
 2820|       |	 */
 2821|       |	(void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
 2822|       |#endif
 2823|     51|}
civetweb.c:consume_socket:
19616|     50|{
19617|     50|	(void)thread_index;
19618|       |
19619|     50|	(void)pthread_mutex_lock(&ctx->thread_mutex);
19620|     50|	DEBUG_TRACE("%s", "going idle");
  ------------------
  |  |  243|     50|	do {                                                                       \
  |  |  244|     50|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
19621|       |
19622|       |	/* If the queue is empty, wait. We're idle at this point. */
19623|    100|	while ((ctx->sq_head == ctx->sq_tail)
  ------------------
  |  Branch (19623:9): [True: 100, False: 0]
  ------------------
19624|    100|	       && (STOP_FLAG_IS_ZERO(&ctx->stop_flag))) {
  ------------------
  |  | 2322|    100|#define STOP_FLAG_IS_ZERO(f) ((*(f)) == 0)
  ------------------
  |  Branch (19624:12): [True: 50, False: 50]
  ------------------
19625|     50|		pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
19626|     50|	}
19627|       |
19628|       |	/* If we're stopping, sq_head may be equal to sq_tail. */
19629|     50|	if (ctx->sq_head > ctx->sq_tail) {
  ------------------
  |  Branch (19629:6): [True: 0, False: 50]
  ------------------
19630|       |		/* Copy socket from the queue and increment tail */
19631|      0|		*sp = ctx->squeue[ctx->sq_tail % ctx->sq_size];
19632|      0|		ctx->sq_tail++;
19633|       |
19634|      0|		DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
  ------------------
  |  |  243|      0|	do {                                                                       \
  |  |  244|      0|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
19635|       |
19636|       |		/* Wrap pointers if needed */
19637|      0|		while (ctx->sq_tail > ctx->sq_size) {
  ------------------
  |  Branch (19637:10): [True: 0, False: 0]
  ------------------
19638|      0|			ctx->sq_tail -= ctx->sq_size;
19639|      0|			ctx->sq_head -= ctx->sq_size;
19640|      0|		}
19641|      0|	}
19642|       |
19643|     50|	(void)pthread_cond_signal(&ctx->sq_empty);
19644|     50|	(void)pthread_mutex_unlock(&ctx->thread_mutex);
19645|       |
19646|     50|	return STOP_FLAG_IS_ZERO(&ctx->stop_flag);
  ------------------
  |  | 2322|     50|#define STOP_FLAG_IS_ZERO(f) ((*(f)) == 0)
  ------------------
19647|     50|}
civetweb.c:master_thread:
20223|      1|{
20224|      1|#if !defined(__ZEPHYR__)
20225|      1|	struct sigaction sa;
20226|       |
20227|       |	/* Ignore SIGPIPE */
20228|      1|	memset(&sa, 0, sizeof(sa));
20229|      1|	sa.sa_handler = SIG_IGN;
20230|      1|	sigaction(SIGPIPE, &sa, NULL);
20231|      1|#endif
20232|       |
20233|      1|	master_thread_run((struct mg_context *)thread_func_param);
20234|      1|	return NULL;
20235|      1|}
civetweb.c:master_thread_run:
20036|      1|{
20037|      1|	struct mg_workerTLS tls;
20038|      1|	struct mg_pollfd *pfd;
20039|      1|	unsigned int i;
20040|      1|	unsigned int workerthreadcount;
20041|       |
20042|      1|	if (!ctx) {
  ------------------
  |  Branch (20042:6): [True: 0, False: 1]
  ------------------
20043|      0|		return;
20044|      0|	}
20045|       |
20046|      1|	mg_set_thread_name("master");
20047|       |
20048|       |	/* Increase priority of the master thread */
20049|       |#if defined(_WIN32)
20050|       |	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
20051|       |#elif defined(USE_MASTER_THREAD_PRIORITY)
20052|       |	int min_prio = sched_get_priority_min(SCHED_RR);
20053|       |	int max_prio = sched_get_priority_max(SCHED_RR);
20054|       |	if ((min_prio >= 0) && (max_prio >= 0)
20055|       |	    && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
20056|       |	    && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
20057|       |		struct sched_param sched_param = {0};
20058|       |		sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
20059|       |		pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
20060|       |	}
20061|       |#endif
20062|       |
20063|       |	/* Initialize thread local storage */
20064|       |#if defined(_WIN32)
20065|       |	tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
20066|       |#endif
20067|      1|	tls.is_master = 1;
20068|      1|	pthread_setspecific(sTlsKey, &tls);
20069|       |
20070|      1|	if (ctx->callbacks.init_thread) {
  ------------------
  |  Branch (20070:6): [True: 0, False: 1]
  ------------------
20071|       |		/* Callback for the master thread (type 0) */
20072|      0|		tls.user_ptr = ctx->callbacks.init_thread(ctx, 0);
20073|      1|	} else {
20074|      1|		tls.user_ptr = NULL;
20075|      1|	}
20076|       |
20077|       |	/* Lua background script "start" event */
20078|       |#if defined(USE_LUA)
20079|       |	if (ctx->lua_background_state) {
20080|       |		lua_State *lstate = (lua_State *)ctx->lua_background_state;
20081|       |		pthread_mutex_lock(&ctx->lua_bg_mutex);
20082|       |
20083|       |		/* call "start()" in Lua */
20084|       |		lua_getglobal(lstate, "start");
20085|       |		if (lua_type(lstate, -1) == LUA_TFUNCTION) {
20086|       |			int ret = lua_pcall(lstate, /* args */ 0, /* results */ 0, 0);
20087|       |			if (ret != 0) {
20088|       |				struct mg_connection fc;
20089|       |				lua_cry(fake_connection(&fc, ctx),
20090|       |				        ret,
20091|       |				        lstate,
20092|       |				        "lua_background_script",
20093|       |				        "start");
20094|       |			}
20095|       |		} else {
20096|       |			lua_pop(lstate, 1);
20097|       |		}
20098|       |
20099|       |		/* determine if there is a "log()" function in Lua background script */
20100|       |		lua_getglobal(lstate, "log");
20101|       |		if (lua_type(lstate, -1) == LUA_TFUNCTION) {
20102|       |			ctx->lua_bg_log_available = 1;
20103|       |		}
20104|       |		lua_pop(lstate, 1);
20105|       |
20106|       |		pthread_mutex_unlock(&ctx->lua_bg_mutex);
20107|       |	}
20108|       |#endif
20109|       |
20110|       |	/* Server starts *now* */
20111|      1|	ctx->start_time = time(NULL);
20112|       |
20113|       |	/* Server accept loop */
20114|      1|	pfd = ctx->listening_socket_fds;
20115|      4|	while (STOP_FLAG_IS_ZERO(&ctx->stop_flag)) {
  ------------------
  |  | 2322|      4|#define STOP_FLAG_IS_ZERO(f) ((*(f)) == 0)
  |  |  ------------------
  |  |  |  Branch (2322:30): [True: 3, False: 1]
  |  |  ------------------
  ------------------
20116|      6|		for (i = 0; i < ctx->num_listening_sockets; i++) {
  ------------------
  |  Branch (20116:15): [True: 3, False: 3]
  ------------------
20117|      3|			pfd[i].fd = ctx->listening_sockets[i].sock;
20118|      3|			pfd[i].events = POLLIN;
20119|      3|		}
20120|       |
20121|      3|		if (mg_poll(pfd,
  ------------------
  |  Branch (20121:7): [True: 0, False: 3]
  ------------------
20122|      3|		            ctx->num_listening_sockets,
20123|      3|		            SOCKET_TIMEOUT_QUANTUM,
  ------------------
  |  |  473|      3|#define SOCKET_TIMEOUT_QUANTUM (2000) /* in ms */
  ------------------
20124|      3|		            &(ctx->stop_flag))
20125|      3|		    > 0) {
20126|      0|			for (i = 0; i < ctx->num_listening_sockets; i++) {
  ------------------
  |  Branch (20126:16): [True: 0, False: 0]
  ------------------
20127|       |				/* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
20128|       |				 * successful poll, and POLLIN is defined as
20129|       |				 * (POLLRDNORM | POLLRDBAND)
20130|       |				 * Therefore, we're checking pfd[i].revents & POLLIN, not
20131|       |				 * pfd[i].revents == POLLIN. */
20132|      0|				if (STOP_FLAG_IS_ZERO(&ctx->stop_flag)
  ------------------
  |  | 2322|      0|#define STOP_FLAG_IS_ZERO(f) ((*(f)) == 0)
  |  |  ------------------
  |  |  |  Branch (2322:30): [True: 0, False: 0]
  |  |  ------------------
  ------------------
20133|      0|				    && (pfd[i].revents & POLLIN)) {
  ------------------
  |  Branch (20133:12): [True: 0, False: 0]
  ------------------
20134|      0|					accept_new_connection(&ctx->listening_sockets[i], ctx);
20135|      0|				}
20136|      0|			}
20137|      0|		}
20138|      3|	}
20139|       |
20140|       |	/* Here stop_flag is 1 - Initiate shutdown. */
20141|      1|	DEBUG_TRACE("%s", "stopping workers");
  ------------------
  |  |  243|      1|	do {                                                                       \
  |  |  244|      1|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
20142|       |
20143|       |	/* Stop signal received: somebody called mg_stop. Quit. */
20144|      1|	close_all_listening_sockets(ctx);
20145|       |
20146|       |	/* Wakeup workers that are waiting for connections to handle. */
20147|       |#if defined(ALTERNATIVE_QUEUE)
20148|       |	for (i = 0; i < ctx->cfg_worker_threads; i++) {
20149|       |		event_signal(ctx->client_wait_events[i]);
20150|       |	}
20151|       |#else
20152|      1|	(void)pthread_mutex_lock(&ctx->thread_mutex);
20153|      1|	pthread_cond_broadcast(&ctx->sq_full);
20154|      1|	(void)pthread_mutex_unlock(&ctx->thread_mutex);
20155|      1|#endif
20156|       |
20157|       |	/* Join all worker threads to avoid leaking threads. */
20158|      1|	workerthreadcount = ctx->cfg_worker_threads;
20159|     51|	for (i = 0; i < workerthreadcount; i++) {
  ------------------
  |  Branch (20159:14): [True: 50, False: 1]
  ------------------
20160|     50|		if (ctx->worker_threadids[i] != 0) {
  ------------------
  |  Branch (20160:7): [True: 50, False: 0]
  ------------------
20161|     50|			mg_join_thread(ctx->worker_threadids[i]);
20162|     50|		}
20163|     50|	}
20164|       |
20165|       |#if defined(USE_LUA)
20166|       |	/* Free Lua state of lua background task */
20167|       |	if (ctx->lua_background_state) {
20168|       |		lua_State *lstate = (lua_State *)ctx->lua_background_state;
20169|       |		ctx->lua_bg_log_available = 0;
20170|       |
20171|       |		/* call "stop()" in Lua */
20172|       |		pthread_mutex_lock(&ctx->lua_bg_mutex);
20173|       |		lua_getglobal(lstate, "stop");
20174|       |		if (lua_type(lstate, -1) == LUA_TFUNCTION) {
20175|       |			int ret = lua_pcall(lstate, /* args */ 0, /* results */ 0, 0);
20176|       |			if (ret != 0) {
20177|       |				struct mg_connection fc;
20178|       |				lua_cry(fake_connection(&fc, ctx),
20179|       |				        ret,
20180|       |				        lstate,
20181|       |				        "lua_background_script",
20182|       |				        "stop");
20183|       |			}
20184|       |		}
20185|       |		DEBUG_TRACE("Close Lua background state %p", lstate);
20186|       |		lua_close(lstate);
20187|       |
20188|       |		ctx->lua_background_state = 0;
20189|       |		pthread_mutex_unlock(&ctx->lua_bg_mutex);
20190|       |	}
20191|       |#endif
20192|       |
20193|      1|	DEBUG_TRACE("%s", "exiting");
  ------------------
  |  |  243|      1|	do {                                                                       \
  |  |  244|      1|	} while (0)
  |  |  ------------------
  |  |  |  Branch (244:11): [Folded - Ignored]
  |  |  ------------------
  ------------------
20194|       |
20195|       |	/* call exit thread callback */
20196|      1|	if (ctx->callbacks.exit_thread) {
  ------------------
  |  Branch (20196:6): [True: 0, False: 1]
  ------------------
20197|       |		/* Callback for the master thread (type 0) */
20198|      0|		ctx->callbacks.exit_thread(ctx, 0, tls.user_ptr);
20199|      0|	}
20200|       |
20201|       |#if defined(_WIN32)
20202|       |	CloseHandle(tls.pthread_cond_helper_mutex);
20203|       |#endif
20204|      1|	pthread_setspecific(sTlsKey, NULL);
20205|       |
20206|       |	/* Signal mg_stop() that we're done.
20207|       |	 * WARNING: This must be the very last thing this
20208|       |	 * thread does, as ctx becomes invalid after this line. */
20209|      1|	STOP_FLAG_ASSIGN(&ctx->stop_flag, 2);
  ------------------
  |  | 2324|      1|#define STOP_FLAG_ASSIGN(f, v) ((*(f)) = (v))
  ------------------
20210|      1|}
civetweb.c:mg_global_lock:
 1095|      1|{
 1096|      1|	(void)pthread_mutex_lock(&global_lock_mutex);
 1097|      1|}
civetweb.c:mg_global_unlock:
 1103|      1|{
 1104|      1|	(void)pthread_mutex_unlock(&global_lock_mutex);
 1105|      1|}

