|  |  |  | @ -207,14 +207,25 @@ static int enqueue_task_locked ( | 
		
	
		
			
				|  |  |  |  | 	qse_httpd_t* httpd, qse_httpd_client_t* client,  | 
		
	
		
			
				|  |  |  |  | 	const qse_httpd_task_t* task, qse_size_t xtnsize) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int ret; | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_lock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | 	ret = enqueue_task_unlocked (httpd, client, task, xtnsize); | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_unlock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | 	return ret; | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	if (httpd->threaded) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		int ret; | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_lock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | 		ret = enqueue_task_unlocked (httpd, client, task, xtnsize); | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_unlock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | 		return ret; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | 		return enqueue_task_unlocked (httpd, client, task, xtnsize); | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int dequeue_task_unlocked ( | 
		
	
		
			
				|  |  |  |  | static QSE_INLINE int dequeue_task_unlocked ( | 
		
	
		
			
				|  |  |  |  | 	qse_httpd_t* httpd, qse_httpd_client_t* client) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	task_queue_node_t* node; | 
		
	
	
		
			
				
					
					|  |  |  | @ -243,18 +254,33 @@ static int dequeue_task_unlocked ( | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int dequeue_task_locked (qse_httpd_t* httpd, qse_httpd_client_t* client) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int ret; | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_lock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | 	ret = dequeue_task_unlocked (httpd, client); | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_unlock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | 	return ret; | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	if (httpd->threaded) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		int ret; | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_lock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | 		ret = dequeue_task_unlocked (httpd, client); | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_unlock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | 		return ret; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | 		return dequeue_task_unlocked (httpd, client); | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static void purge_tasks_locked (qse_httpd_t* httpd, qse_httpd_client_t* client) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_lock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	if (httpd->threaded) pthread_mutex_lock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | 	while (dequeue_task_unlocked (httpd, client) == 0); | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_unlock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	if (httpd->threaded) pthread_mutex_unlock (&client->task.mutex); | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int capture_param (qse_htrd_t* http, const qse_mcstr_t* key, const qse_mcstr_t* val) | 
		
	
	
		
			
				
					
					|  |  |  | @ -488,7 +514,7 @@ static void deactivate_listener (qse_httpd_t* httpd, listener_t* l) | 
		
	
		
			
				|  |  |  |  | 	l->handle = -1; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int activate_listner (qse_httpd_t* httpd, listener_t* l) | 
		
	
		
			
				|  |  |  |  | static int activate_listener (qse_httpd_t* httpd, listener_t* l) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | /* TODO: suport https... */ | 
		
	
		
			
				|  |  |  |  | 	sockaddr_t addr; | 
		
	
	
		
			
				
					
					|  |  |  | @ -571,7 +597,7 @@ static void deactivate_listeners (qse_httpd_t* httpd) | 
		
	
		
			
				|  |  |  |  | 	httpd->listener.max = -1; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int activate_listners (qse_httpd_t* httpd) | 
		
	
		
			
				|  |  |  |  | static int activate_listeners (qse_httpd_t* httpd) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	listener_t* l; | 
		
	
		
			
				|  |  |  |  | 	fd_set listener_set; | 
		
	
	
		
			
				
					
					|  |  |  | @ -582,7 +608,7 @@ static int activate_listners (qse_httpd_t* httpd) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (l->handle <= -1) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (activate_listner (httpd, l) <= -1) goto oops; | 
		
	
		
			
				|  |  |  |  | 			if (activate_listener (httpd, l) <= -1) goto oops; | 
		
	
		
			
				|  |  |  |  | /*TODO: callback httpd->cbs.listener_activated (httpd, l);*/ | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @ -613,7 +639,9 @@ static void delete_from_client_array (qse_httpd_t* httpd, int fd) | 
		
	
		
			
				|  |  |  |  | 	if (array->data[fd].htrd) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		purge_tasks_locked (httpd, &array->data[fd]); | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_destroy (&array->data[fd].task.mutex); | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 		if (httpd->threaded) pthread_mutex_destroy (&array->data[fd].task.mutex); | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		qse_htrd_close (array->data[fd].htrd); | 
		
	
		
			
				|  |  |  |  | 		array->data[fd].htrd = QSE_NULL;	 | 
		
	
	
		
			
				
					
					|  |  |  | @ -674,7 +702,10 @@ static qse_httpd_client_t* insert_into_client_array (qse_httpd_t* httpd, int fd, | 
		
	
		
			
				|  |  |  |  | 	array->data[fd].handle.i = fd;	 | 
		
	
		
			
				|  |  |  |  | 	array->data[fd].addr = *addr; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_init (&array->data[fd].task.mutex, NULL); | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	if (httpd->threaded)  | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_init (&array->data[fd].task.mutex, QSE_NULL); | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	xtn = (htrd_xtn_t*)qse_htrd_getxtn (array->data[fd].htrd);	 | 
		
	
		
			
				|  |  |  |  | 	xtn->client_index = fd;  | 
		
	
	
		
			
				
					
					|  |  |  | @ -726,9 +757,15 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n")); | 
		
	
		
			
				|  |  |  |  | 	if (flag >= 0) fcntl (c, F_SETFL, flag | O_NONBLOCK); | 
		
	
		
			
				|  |  |  |  | 	fcntl (c, F_SETFD, FD_CLOEXEC); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_lock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	if (httpd->threaded) pthread_mutex_lock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | 	client = insert_into_client_array (httpd, c, &addr); | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_unlock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	if (httpd->threaded) pthread_mutex_unlock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (client == QSE_NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		close (c); | 
		
	
	
		
			
				
					
					|  |  |  | @ -759,7 +796,8 @@ httpd->cbs.on_error (httpd, l).... */ | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int make_fd_set_from_client_array (qse_httpd_t* httpd, fd_set* r, fd_set* w) | 
		
	
		
			
				|  |  |  |  | static int make_fd_set_from_client_array ( | 
		
	
		
			
				|  |  |  |  | 	qse_httpd_t* httpd, fd_set* r, fd_set* w) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int fd, max = -1; | 
		
	
		
			
				|  |  |  |  | 	client_array_t* ca = &httpd->client.array; | 
		
	
	
		
			
				
					
					|  |  |  | @ -816,6 +854,7 @@ static void perform_task (qse_httpd_t* httpd, qse_httpd_client_t* client) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | static void* response_thread (void* arg) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	qse_httpd_t* httpd = (qse_httpd_t*)arg; | 
		
	
	
		
			
				
					
					|  |  |  | @ -830,7 +869,7 @@ static void* response_thread (void* arg) | 
		
	
		
			
				|  |  |  |  | 		tv.tv_usec = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_lock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | 		max = make_fd_set_from_client_array (httpd, NULL, &w); | 
		
	
		
			
				|  |  |  |  | 		max = make_fd_set_from_client_array (httpd, QSE_NULL, &w); | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_unlock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		while (max == -1 && !httpd->stopreq) | 
		
	
	
		
			
				
					
					|  |  |  | @ -840,22 +879,22 @@ static void* response_thread (void* arg) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			pthread_mutex_lock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			gettimeofday (&now, NULL); | 
		
	
		
			
				|  |  |  |  | 			gettimeofday (&now, QSE_NULL); | 
		
	
		
			
				|  |  |  |  | 			timeout.tv_sec = now.tv_sec + 2; | 
		
	
		
			
				|  |  |  |  | 			timeout.tv_nsec = now.tv_usec * 1000; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			pthread_cond_timedwait (&httpd->client.cond, &httpd->client.mutex, &timeout); | 
		
	
		
			
				|  |  |  |  | 			max = make_fd_set_from_client_array (httpd, NULL, &w); | 
		
	
		
			
				|  |  |  |  | 			max = make_fd_set_from_client_array (httpd, QSE_NULL, &w); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			pthread_mutex_unlock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (httpd->stopreq) break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		n = select (max + 1, NULL, &w, NULL, &tv); | 
		
	
		
			
				|  |  |  |  | 		n = select (max + 1, QSE_NULL, &w, QSE_NULL, &tv); | 
		
	
		
			
				|  |  |  |  | 		if (n <= -1) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (errno == EINTR) continue; | 
		
	
		
			
				|  |  |  |  | 			/*if (errno == EINTR) continue; */ | 
		
	
		
			
				|  |  |  |  | qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure - %S\n"), strerror(errno)); | 
		
	
		
			
				|  |  |  |  | 			/* break; */ | 
		
	
		
			
				|  |  |  |  | 			continue; | 
		
	
	
		
			
				
					
					|  |  |  | @ -886,13 +925,13 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure - %S\n"), strerro | 
		
	
		
			
				|  |  |  |  | 					perform_task (httpd, client); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	pthread_exit (NULL); | 
		
	
		
			
				|  |  |  |  | 	return NULL; | 
		
	
		
			
				|  |  |  |  | 	pthread_exit (QSE_NULL); | 
		
	
		
			
				|  |  |  |  | 	return QSE_NULL; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int read_from_client (qse_httpd_t* httpd, qse_httpd_client_t* client) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					
					|  |  |  | @ -939,9 +978,11 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: http error while processing \n")); | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | int qse_httpd_loop (qse_httpd_t* httpd) | 
		
	
		
			
				|  |  |  |  | int qse_httpd_loop (qse_httpd_t* httpd, int threaded) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	pthread_t response_thread_id; | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	httpd->stopreq = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @ -951,48 +992,52 @@ int qse_httpd_loop (qse_httpd_t* httpd) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (httpd->listener.list == QSE_NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		/* no listener specified */ | 
		
	
		
			
				|  |  |  |  | 		httpd->errnum = QSE_HTTPD_EINVAL; | 
		
	
		
			
				|  |  |  |  | 		goto oops; | 
		
	
		
			
				|  |  |  |  | 		return -1; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (activate_listners (httpd) <= -1) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		qse_fprintf (QSE_STDERR, QSE_T("Error: failed to make a server socket\n")); | 
		
	
		
			
				|  |  |  |  | 		goto oops; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	/* data receiver main logic */ | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_init (&httpd->client.mutex, NULL); | 
		
	
		
			
				|  |  |  |  | 	pthread_cond_init (&httpd->client.cond, NULL); | 
		
	
		
			
				|  |  |  |  | 	if (activate_listeners (httpd) <= -1) return -1; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	init_client_array (httpd); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	/* start the response sender as a thread */ | 
		
	
		
			
				|  |  |  |  | 	pthread_create (&response_thread_id, NULL, response_thread, httpd); | 
		
	
		
			
				|  |  |  |  | /* TODO: error check */ | 
		
	
		
			
				|  |  |  |  | 	if (threaded) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_init (&httpd->client.mutex, QSE_NULL); | 
		
	
		
			
				|  |  |  |  | 		pthread_cond_init (&httpd->client.cond, QSE_NULL); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (pthread_create (&response_thread_id, QSE_NULL, response_thread, httpd) != 0)  | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			pthread_cond_destroy (&httpd->client.cond); | 
		
	
		
			
				|  |  |  |  | 			pthread_mutex_destroy (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | 			httpd->threaded = 0; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		else httpd->threaded = 1; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	while (!httpd->stopreq) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		int n, max, fd; | 
		
	
		
			
				|  |  |  |  | 		fd_set r; | 
		
	
		
			
				|  |  |  |  | 		fd_set w; | 
		
	
		
			
				|  |  |  |  | 		struct timeval tv; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		tv.tv_sec = 1; | 
		
	
		
			
				|  |  |  |  | 		tv.tv_usec = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_lock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | 		max = make_fd_set_from_client_array (httpd, &r, QSE_NULL); | 
		
	
		
			
				|  |  |  |  | 		max = make_fd_set_from_client_array (httpd, &r, &w); | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_unlock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		n = select (max + 1, &r, NULL, NULL, &tv); | 
		
	
		
			
				|  |  |  |  | 		n = select (max + 1, &r, &w, QSE_NULL, &tv); | 
		
	
		
			
				|  |  |  |  | 		if (n <= -1) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			httpd->errnum = QSE_HTTPD_EIOMUX; | 
		
	
		
			
				|  |  |  |  | /* TODO: call user callback for this multiplexer error */ | 
		
	
		
			
				|  |  |  |  | 			if (errno == EINTR) continue; | 
		
	
		
			
				|  |  |  |  | 			/*if (errno == EINTR) continue;*/ | 
		
	
		
			
				|  |  |  |  | qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure\n")); | 
		
	
		
			
				|  |  |  |  | 			/* break; */ | 
		
	
		
			
				|  |  |  |  | 			continue; | 
		
	
	
		
			
				
					
					|  |  |  | @ -1014,33 +1059,57 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure\n")); | 
		
	
		
			
				|  |  |  |  | 				/* got input */ | 
		
	
		
			
				|  |  |  |  | 				if (read_from_client (httpd, client) <= -1) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					qse_httpd_markclientbad (httpd, client); | 
		
	
		
			
				|  |  |  |  | 					shutdown (client->handle.i, 0); | 
		
	
		
			
				|  |  |  |  | 				#if 0 | 
		
	
		
			
				|  |  |  |  | 					pthread_mutex_lock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | 					delete_from_client_array (httpd, fd);      | 
		
	
		
			
				|  |  |  |  | 					pthread_mutex_unlock (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | 				#endif | 
		
	
		
			
				|  |  |  |  | 					if (httpd->threaded) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						/* let the writing part handle it,   | 
		
	
		
			
				|  |  |  |  | 						 * probably in the next iteration */ | 
		
	
		
			
				|  |  |  |  | 						qse_httpd_markclientbad (httpd, client); | 
		
	
		
			
				|  |  |  |  | 						shutdown (client->handle.i, 0); | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 					else | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						/*pthread_mutex_lock (&httpd->client.mutex);*/ | 
		
	
		
			
				|  |  |  |  | 						delete_from_client_array (httpd, fd);      | 
		
	
		
			
				|  |  |  |  | 						/*pthread_mutex_unlock (&httpd->client.mutex);*/ | 
		
	
		
			
				|  |  |  |  | 						continue; /* don't need to go to the writing part */		 | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (!httpd->threaded && FD_ISSET(client->handle.i, &w))  | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				/* output is handled in the main loop if and  | 
		
	
		
			
				|  |  |  |  | 				 * only if it is not threaded */ | 
		
	
		
			
				|  |  |  |  | 				if (client->bad)  | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					/*send (client->handle, i, "INTERNAL SERVER ERROR..", ...);*/ | 
		
	
		
			
				|  |  |  |  | 					/*shutdown (client->handle.i, 0);*/ | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					/*pthread_mutex_lock (&httpd->client.mutex);*/ | 
		
	
		
			
				|  |  |  |  | 					delete_from_client_array (httpd, fd);      | 
		
	
		
			
				|  |  |  |  | 					/*pthread_mutex_unlock (&httpd->client.mutex);*/ | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				else if (client->task.queue.count > 0)  | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					perform_task (httpd, client); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	pthread_join (response_thread_id, NULL); | 
		
	
		
			
				|  |  |  |  | 	if (httpd->threaded)  | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		pthread_join (response_thread_id, QSE_NULL); | 
		
	
		
			
				|  |  |  |  | 		pthread_cond_destroy (&httpd->client.cond); | 
		
	
		
			
				|  |  |  |  | 		pthread_mutex_destroy (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	fini_client_array (httpd); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	pthread_cond_destroy (&httpd->client.cond); | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_destroy (&httpd->client.mutex); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	deactivate_listeners (httpd); | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | oops: | 
		
	
		
			
				|  |  |  |  | 	deactivate_listeners (httpd); | 
		
	
		
			
				|  |  |  |  | 	return -1; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static void free_listener (qse_httpd_t* httpd, listener_t* l) | 
		
	
	
		
			
				
					
					|  |  |  | @ -1267,7 +1336,7 @@ void qse_httpd_clearlisteners (qse_httpd_t* httpd) | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_lock (&httpd->listener.mutex); | 
		
	
		
			
				|  |  |  |  | 	deactivate_listeners (httpd); | 
		
	
		
			
				|  |  |  |  | 	free_listener_list (httpd, httpd->listener.list); | 
		
	
		
			
				|  |  |  |  | 	httpd->listener.list = NULL; | 
		
	
		
			
				|  |  |  |  | 	httpd->listener.list = QSE_NULL; | 
		
	
		
			
				|  |  |  |  | 	pthread_mutex_unlock (&httpd->listener.mutex); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
	
		
			
				
					
					|  |  |  | @ -1279,7 +1348,9 @@ int qse_httpd_entask ( | 
		
	
		
			
				|  |  |  |  | 	int ret; | 
		
	
		
			
				|  |  |  |  | 	ret = enqueue_task_locked (httpd, client, task, xtnsize); | 
		
	
		
			
				|  |  |  |  | 	if (ret <= -1) client->bad = 1; /* mark this client bad */ | 
		
	
		
			
				|  |  |  |  | 	else pthread_cond_signal (&httpd->client.cond); | 
		
	
		
			
				|  |  |  |  | #if defined(HAVE_PTHREAD) | 
		
	
		
			
				|  |  |  |  | 	else if (httpd->threaded) pthread_cond_signal (&httpd->client.cond); | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  | 	return ret; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | 
 |