request_t.redirect takes variable argument list
request_t.serve to serve non-template data fixed dispatcher thread locking code
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
#include <utils/linked_list.h>
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
typedef struct private_dispatcher_t private_dispatcher_t;
|
typedef struct private_dispatcher_t private_dispatcher_t;
|
||||||
@@ -122,8 +123,8 @@ typedef struct {
|
|||||||
session_t *session;
|
session_t *session;
|
||||||
/** condvar to wait for session */
|
/** condvar to wait for session */
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
/** number of threads waiting for session */
|
/** TRUE if session is in use */
|
||||||
int waiting;
|
bool in_use;
|
||||||
/** last use of the session */
|
/** last use of the session */
|
||||||
time_t used;
|
time_t used;
|
||||||
} session_entry_t;
|
} session_entry_t;
|
||||||
@@ -164,7 +165,7 @@ static session_entry_t *session_entry_create(private_dispatcher_t *this)
|
|||||||
session_entry_t *entry;
|
session_entry_t *entry;
|
||||||
|
|
||||||
entry = malloc_thing(session_entry_t);
|
entry = malloc_thing(session_entry_t);
|
||||||
entry->waiting = 1;
|
entry->in_use = FALSE;
|
||||||
pthread_cond_init(&entry->cond, NULL);
|
pthread_cond_init(&entry->cond, NULL);
|
||||||
entry->session = load_session(this);
|
entry->session = load_session(this);
|
||||||
entry->used = time(NULL);
|
entry->used = time(NULL);
|
||||||
@@ -228,11 +229,12 @@ static void dispatch(private_dispatcher_t *this)
|
|||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
|
|
||||||
/* find session */
|
/* find session */
|
||||||
iterator = this->sessions->create_iterator_locked(this->sessions, &this->mutex);
|
pthread_mutex_lock(&this->mutex);
|
||||||
|
iterator = this->sessions->create_iterator(this->sessions, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)¤t))
|
while (iterator->iterate(iterator, (void**)¤t))
|
||||||
{
|
{
|
||||||
/* check all sessions for timeout */
|
/* check all sessions for timeout */
|
||||||
if (current->waiting == 0 &&
|
if (!current->in_use &&
|
||||||
current->used < now - this->timeout)
|
current->used < now - this->timeout)
|
||||||
{
|
{
|
||||||
iterator->remove(iterator);
|
iterator->remove(iterator);
|
||||||
@@ -243,27 +245,24 @@ static void dispatch(private_dispatcher_t *this)
|
|||||||
streq(current->session->get_sid(current->session), sid))
|
streq(current->session->get_sid(current->session), sid))
|
||||||
{
|
{
|
||||||
found = current;
|
found = current;
|
||||||
found->waiting++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
{ /* wait until session is unused */
|
{ /* wait until session is unused */
|
||||||
pthread_mutex_lock(&this->mutex);
|
while (found->in_use)
|
||||||
while (found->waiting > 1)
|
|
||||||
{
|
{
|
||||||
pthread_cond_wait(&found->cond, &this->mutex);
|
pthread_cond_wait(&found->cond, &this->mutex);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&this->mutex);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* create a new session if not found */
|
{ /* create a new session if not found */
|
||||||
found = session_entry_create(this);
|
found = session_entry_create(this);
|
||||||
pthread_mutex_lock(&this->mutex);
|
|
||||||
this->sessions->insert_first(this->sessions, found);
|
this->sessions->insert_first(this->sessions, found);
|
||||||
pthread_mutex_unlock(&this->mutex);
|
|
||||||
}
|
}
|
||||||
|
found->in_use = TRUE;
|
||||||
|
pthread_mutex_unlock(&this->mutex);
|
||||||
|
|
||||||
/* start processing */
|
/* start processing */
|
||||||
found->session->process(found->session, request);
|
found->session->process(found->session, request);
|
||||||
@@ -271,7 +270,7 @@ static void dispatch(private_dispatcher_t *this)
|
|||||||
|
|
||||||
/* release session */
|
/* release session */
|
||||||
pthread_mutex_lock(&this->mutex);
|
pthread_mutex_lock(&this->mutex);
|
||||||
found->waiting--;
|
found->in_use = FALSE;
|
||||||
pthread_cond_signal(&found->cond);
|
pthread_cond_signal(&found->cond);
|
||||||
pthread_mutex_unlock(&this->mutex);
|
pthread_mutex_unlock(&this->mutex);
|
||||||
|
|
||||||
|
|||||||
@@ -179,12 +179,18 @@ static void add_cookie(private_request_t *this, char *name, char *value)
|
|||||||
/**
|
/**
|
||||||
* Implementation of request_t.redirect.
|
* Implementation of request_t.redirect.
|
||||||
*/
|
*/
|
||||||
static void redirect(private_request_t *this, char *location)
|
static void redirect(private_request_t *this, char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
FCGX_FPrintF(this->req->out, "Status: 303 See Other\n");
|
FCGX_FPrintF(this->req->out, "Status: 303 See Other\n");
|
||||||
FCGX_FPrintF(this->req->out, "Location: %s%s%s\n\n",
|
FCGX_FPrintF(this->req->out, "Location: %s%s",
|
||||||
FCGX_GetParam("SCRIPT_NAME", this->req->envp),
|
FCGX_GetParam("SCRIPT_NAME", this->req->envp),
|
||||||
*location == '/' ? "" : "/", location);
|
*fmt == '/' ? "" : "/");
|
||||||
|
va_start(args, fmt);
|
||||||
|
FCGX_VFPrintF(this->req->out, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
FCGX_FPrintF(this->req->out, "\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,6 +201,16 @@ static char* get_base(private_request_t *this)
|
|||||||
return FCGX_GetParam("SCRIPT_NAME", this->req->envp);
|
return FCGX_GetParam("SCRIPT_NAME", this->req->envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of request_t.serve.
|
||||||
|
*/
|
||||||
|
static void serve(private_request_t *this, char *headers, chunk_t chunk)
|
||||||
|
{
|
||||||
|
FCGX_FPrintF(this->req->out, "%s\n\n", headers);
|
||||||
|
|
||||||
|
FCGX_PutStr(chunk.ptr, chunk.len, this->req->out);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of request_t.render.
|
* Implementation of request_t.render.
|
||||||
*/
|
*/
|
||||||
@@ -254,8 +270,9 @@ request_t *request_create(FCGX_Request *request, bool debug)
|
|||||||
this->public.add_cookie = (void(*)(request_t*, char *name, char *value))add_cookie;
|
this->public.add_cookie = (void(*)(request_t*, char *name, char *value))add_cookie;
|
||||||
this->public.get_cookie = (char*(*)(request_t*,char*))get_cookie;
|
this->public.get_cookie = (char*(*)(request_t*,char*))get_cookie;
|
||||||
this->public.get_query_data = (char*(*)(request_t*, char *name))get_query_data;
|
this->public.get_query_data = (char*(*)(request_t*, char *name))get_query_data;
|
||||||
this->public.redirect = (void(*)(request_t*, char *location))redirect;
|
this->public.redirect = (void(*)(request_t*, char *fmt,...))redirect;
|
||||||
this->public.render = (void(*)(request_t*,char*))render;
|
this->public.render = (void(*)(request_t*,char*))render;
|
||||||
|
this->public.serve = (void(*)(request_t*,char*,chunk_t))serve;
|
||||||
this->public.set = (void(*)(request_t*, char *, char*))set;
|
this->public.set = (void(*)(request_t*, char *, char*))set;
|
||||||
this->public.setf = (void(*)(request_t*, char *format, ...))setf;
|
this->public.setf = (void(*)(request_t*, char *format, ...))setf;
|
||||||
this->public.destroy = (void(*)(request_t*))destroy;
|
this->public.destroy = (void(*)(request_t*))destroy;
|
||||||
|
|||||||
@@ -75,9 +75,10 @@ struct request_t {
|
|||||||
/**
|
/**
|
||||||
* @brief Redirect the client to another location.
|
* @brief Redirect the client to another location.
|
||||||
*
|
*
|
||||||
* @param location location to redirect to
|
* @param fmt location format string
|
||||||
|
* @param ... variable argument for fmt
|
||||||
*/
|
*/
|
||||||
void (*redirect)(request_t *this, char *location);
|
void (*redirect)(request_t *this, char *fmt, ...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set a template value.
|
* @brief Set a template value.
|
||||||
@@ -106,10 +107,17 @@ struct request_t {
|
|||||||
* other targets without to worry about path location.
|
* other targets without to worry about path location.
|
||||||
*
|
*
|
||||||
* @param template clearsilver template file location
|
* @param template clearsilver template file location
|
||||||
* @return rendered template string
|
|
||||||
*/
|
*/
|
||||||
void (*render)(request_t *this, char *template);
|
void (*render)(request_t *this, char *template);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Serve a request with headers and a body.
|
||||||
|
*
|
||||||
|
* @param headers HTTP headers, \n separated
|
||||||
|
* @param chunk body to write to output
|
||||||
|
*/
|
||||||
|
void (*serve)(request_t *this, char *headers, chunk_t chunk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroy the request_t.
|
* @brief Destroy the request_t.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user