#include <signal.h>
#include <unistd.h>
+#include <debug.h>
#include <utils/linked_list.h>
typedef struct private_dispatcher_t private_dispatcher_t;
session_t *session;
/** condvar to wait for session */
pthread_cond_t cond;
- /** number of threads waiting for session */
- int waiting;
+ /** TRUE if session is in use */
+ bool in_use;
/** last use of the session */
time_t used;
} session_entry_t;
session_entry_t *entry;
entry = malloc_thing(session_entry_t);
- entry->waiting = 1;
+ entry->in_use = FALSE;
pthread_cond_init(&entry->cond, NULL);
entry->session = load_session(this);
entry->used = time(NULL);
now = time(NULL);
/* 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))
{
/* check all sessions for timeout */
- if (current->waiting == 0 &&
+ if (!current->in_use &&
current->used < now - this->timeout)
{
iterator->remove(iterator);
streq(current->session->get_sid(current->session), sid))
{
found = current;
- found->waiting++;
}
}
iterator->destroy(iterator);
if (found)
{ /* wait until session is unused */
- pthread_mutex_lock(&this->mutex);
- while (found->waiting > 1)
+ while (found->in_use)
{
pthread_cond_wait(&found->cond, &this->mutex);
}
- pthread_mutex_unlock(&this->mutex);
}
else
{ /* create a new session if not found */
found = session_entry_create(this);
- pthread_mutex_lock(&this->mutex);
this->sessions->insert_first(this->sessions, found);
- pthread_mutex_unlock(&this->mutex);
}
+ found->in_use = TRUE;
+ pthread_mutex_unlock(&this->mutex);
/* start processing */
found->session->process(found->session, request);
/* release session */
pthread_mutex_lock(&this->mutex);
- found->waiting--;
+ found->in_use = FALSE;
pthread_cond_signal(&found->cond);
pthread_mutex_unlock(&this->mutex);
/**
* 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, "Location: %s%s%s\n\n",
+ FCGX_FPrintF(this->req->out, "Location: %s%s",
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");
}
/**
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.
*/
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_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.serve = (void(*)(request_t*,char*,chunk_t))serve;
this->public.set = (void(*)(request_t*, char *, char*))set;
this->public.setf = (void(*)(request_t*, char *format, ...))setf;
this->public.destroy = (void(*)(request_t*))destroy;
/**
* @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.
* other targets without to worry about path location.
*
* @param template clearsilver template file location
- * @return rendered template string
*/
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.
*/