From 1361f0e88138653d2437f45ddf940206ed0e93b7 Mon Sep 17 00:00:00 2001 From: Jakub Sławiński Date: Thu, 6 Apr 2006 23:34:51 +0200 Subject: v0.8.1 - Fixed: enableproxy option in server's config file - Added: clients idle time - Added: 'maxidle' option - Modified: task scheduling subsystem has been completely rewritten - Fixed: segmentation fault in http tunnels after multiple simultaneous POST connections from the same source - Fixed: unexpected connection close when http proxy was too slow - Fixed: SIGSEGV in http proxy mode under cygwin - Added: enabled the SO_KEEPALIVE option for all the sockets used by the apf - Added: 60 seconds timeout for SSL_connect --- src/task_scheduler_struct.c | 321 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 src/task_scheduler_struct.c (limited to 'src/task_scheduler_struct.c') diff --git a/src/task_scheduler_struct.c b/src/task_scheduler_struct.c new file mode 100644 index 0000000..b96a919 --- /dev/null +++ b/src/task_scheduler_struct.c @@ -0,0 +1,321 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2006 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include + +#include "timeval_functions.h" +#include "task_scheduler_struct.h" + +/* + * Function name: TaskScheduler_new + * Description: Creates and initializes task scheduler. + * Returns: Pointer to newly created TaskScheduler structure. + */ + +TaskScheduler* +TaskScheduler_new() +{ + TaskScheduler* tmp = calloc(1, sizeof(TaskScheduler)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + + return tmp; +} + +/* + * Function name: TaskScheduler_free + * Description: Frees the memory allocated for TaskScheduler structure. + * Arguments: scheduler - pointer to pointer to TaskScheduler structure + */ + +void +TaskScheduler_free(TaskScheduler** scheduler) +{ + assert(scheduler != NULL); + if (scheduler == NULL) { + return; + } + assert((*scheduler) != NULL); + if ((*scheduler) == NULL) { + return; + } + + while ((*scheduler)->head) { + TaskScheduler_removeTask((*scheduler), TaskListNode_get_task((*scheduler)->head)); + } + + free((*scheduler)); + (*scheduler) = NULL; +} + +/* + * Function name: TaskScheduler_get_actualTimer + * Description: Returns the smallest timeval structure in the scheduler. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: The smallest timeval structure in the scheduler. + */ + +struct timeval* +TaskScheduler_get_actualTimer(TaskScheduler* scheduler) +{ + assert(scheduler != NULL); + if (scheduler == NULL) { + return NULL; + } + return Task_get_timer(TaskListNode_get_task(scheduler->actualTask)); +} + +/* + * Function name: TaskScheduler_hasMoreTasks + * Description: Checks if there is more tasks in the scheduler. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: 0 - there is no more tasks in the scheduler, + * n>0 - there is more (n) tasks in the scheduler. + */ + +int +TaskScheduler_hasMoreTasks(TaskScheduler* scheduler) +{ + assert(scheduler != NULL); + if (scheduler == NULL) { + return 0; + } + return scheduler->numberOfTasks; +} + +/* + * Function name: TaskScheduler_addTask + * Description: Adds the task to the scheduler. + * Arguments: scheduler - pointer to TaskScheduler structure + * task - the task to add to the scheduler + * Returns: 0 - the task has been added successfully, + * 1 - the task has NOT been added. + */ + +int +TaskScheduler_addTask(TaskScheduler* scheduler, Task* task) +{ + TaskListNode* tmp; + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + assert(task != NULL); + if (task == NULL) { + return 1; + } + tmp = TaskListNode_new(task); + assert(tmp != NULL); + if (tmp == NULL) { + return 1; + } + if (scheduler->head) { + TaskListNode_set_next(tmp, scheduler->head); + TaskListNode_set_previous(scheduler->head, tmp); + } + scheduler->head = tmp; + scheduler->numberOfTasks += 1; + if (scheduler->actualTask) { + if (timeval_compare(TaskScheduler_get_actualTimer(scheduler), Task_get_timer(task)) > 0) { + scheduler->actualTask = tmp; + } + } + else { + scheduler->actualTask = tmp; + } + return 0; +} + +/* + * Function name: find_tasknode_with_minimal_timer + * Description: Finds the task list node with minimal timer. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: The task list node with minimal timer. + */ +static TaskListNode* +find_tasknode_with_minimal_timer(TaskScheduler* scheduler) +{ + TaskListNode* iterator; + TaskListNode* candidate; + assert(scheduler != NULL); + if (scheduler == NULL) { + return NULL; + } + if (scheduler->head == NULL) { + return NULL; + } + candidate = scheduler->head; + iterator = scheduler->head; + iterator = iterator->next; + while (iterator) { + if (timeval_compare(Task_get_timer(TaskListNode_get_task(iterator)), + Task_get_timer(TaskListNode_get_task(candidate))) == -1) { + candidate = iterator; + } + iterator = iterator->next; + } + return candidate; +} + +/* + * Function name: TaskScheduler_removeTask + * Description: Removes the task from the scheduler. + * Arguments: scheduler - pointer to TaskScheduler structure + * task - the task to remove from the scheduler + * Returns: 0 - the task has been removed successfully, + * 1 - the task has NOT been removed (probably there was no such task in the scheduler). + */ + +int +TaskScheduler_removeTask(TaskScheduler* scheduler, Task* task) +{ + TaskListNode* iterator; + Task* tmp; + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + assert(task != NULL); + if (task == NULL) { + return 1; + } + iterator = scheduler->head; + while (iterator) { + tmp = TaskListNode_get_task(iterator); + if (tmp == task) { + if (iterator->previous) { + TaskListNode_set_next(iterator->previous, iterator->next); + } + if (iterator->next) { + TaskListNode_set_previous(iterator->next, iterator->previous); + } + if (iterator == scheduler->head) { + scheduler->head = iterator->next; + } + if (iterator == scheduler->actualTask) { + scheduler->actualTask = find_tasknode_with_minimal_timer(scheduler); + } + scheduler->numberOfTasks -= 1; + TaskListNode_free(&iterator); + return 0; + } + iterator = iterator->next; + } + return 1; +} + +/* + * Function name: TaskScheduler_startWatching + * Description: Starts counting the time for the actual timer. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: 0 - success, + * 1 - failure. + */ + +int +TaskScheduler_startWatching(TaskScheduler* scheduler) +{ + struct timeval* tmp; + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + tmp = TaskScheduler_get_actualTimer(scheduler); + assert(tmp != NULL); + if (tmp == NULL) { + return 1; + } + scheduler->delta = *tmp; + return 0; +} + +/* + * Function name: TaskScheduler_stopWatching + * Description: Stops counting the time for the actual timer. + * Updates all the timers and destroys them if needed. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: 0 - success, + * 1 - failure. + */ + +int +TaskScheduler_stopWatching(TaskScheduler* scheduler) +{ + TaskListNode* iterator; + TaskListNode* actualTask; + Task* backup; + struct timeval* tmp; + int result; + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + tmp = TaskScheduler_get_actualTimer(scheduler); + assert(tmp != NULL); + if (tmp == NULL) { + return 1; + } + if (timeval_subtract(&(scheduler->delta), tmp)) { + return 1; + } + actualTask = scheduler->actualTask; + assert(scheduler->actualTask != NULL); + iterator = scheduler->head; + while (iterator) { + if (iterator != actualTask) { + result = timeval_subtract(Task_get_timer(TaskListNode_get_task(iterator)), &(scheduler->delta)); + assert(result == 0); + } + if (timeval_lq_zero(Task_get_timer(TaskListNode_get_task(iterator)))) { + Task_exec(TaskListNode_get_task(iterator)); + backup = TaskListNode_get_task(iterator); + iterator = iterator->next; + TaskScheduler_removeTask(scheduler, backup); + continue; + } + iterator = iterator->next; + } + TaskScheduler_update(scheduler); + return 0; +} + +/* + * Function name: TaskScheduler_update + * Description: Updates the actual timer. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: 0 - success, + * 1 - failure. + */ + +int +TaskScheduler_update(TaskScheduler* scheduler) +{ + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + scheduler->actualTask = find_tasknode_with_minimal_timer(scheduler); + return 0; +} -- cgit v1.1