*/
void RemoveContext (struct CitContext *con)
{
- struct CitContext *ptr = NULL;
- struct CitContext *ToFree = NULL;
-
if (con==NULL) {
lprintf(CTDL_ERR, "WARNING: RemoveContext() called with NULL!\n");
return;
*/
lprintf(CTDL_DEBUG, "Removing context for session %d\n", con->cs_pid);
begin_critical_section(S_SESSION_TABLE);
- if (ContextList == con) {
- ToFree = ContextList;
- ContextList = ContextList->next;
- --num_sessions;
- }
- else {
- for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
- if (ptr->next == con) {
- /* See fair scheduling in sysdep.c */
- if (next_session == ptr->next)
- next_session = ptr->next->next;
- ToFree = ptr->next;
- ptr->next = ptr->next->next;
- --num_sessions;
- }
- }
- }
+ if (con->prev) con->prev->next = con->next; else ContextList = con->next;
+ if (con->next) con->next->prev = con->prev;
+ --num_sessions;
end_critical_section(S_SESSION_TABLE);
- if (ToFree == NULL) {
- lprintf(CTDL_DEBUG, "RemoveContext() found nothing to remove\n");
- return;
- }
-
/* Run any cleanup routines registered by loadable modules.
* Note 1: This must occur *before* deallocate_user_data() because the
* cleanup functions might touch dynamic session data.
#include <limits.h>
#include <sys/resource.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/un.h>
if (ContextList == NULL) {
ContextList = me;
me->cs_pid = 1;
+ me->prev = NULL;
me->next = NULL;
}
else if (ContextList->cs_pid > 1) {
+ me->prev = NULL;
me->next = ContextList;
ContextList = me;
me->cs_pid = 1;
if (ptr->next == NULL) {
ptr->next = me;
me->cs_pid = ptr->cs_pid + 1;
+ me->prev = ptr;
me->next = NULL;
goto DONE;
}
else if (ptr->next->cs_pid > (ptr->cs_pid+1)) {
+ me->prev = ptr;
me->next = ptr->next;
+ ptr->next->prev = me;
ptr->next = me;
me->cs_pid = ptr->cs_pid + 1;
goto DONE;
/*
- * buffer_output() ... tell client_write to buffer all output until
- * instructed to dump it all out later
+ * The following functions implement output buffering. If the kernel supplies
+ * native TCP buffering (Linux & *BSD), use that; otherwise, emulate it with
+ * user-space buffering.
*/
+#ifdef TCP_CORK
+# define HAVE_TCP_BUFFERING
+#else
+# ifdef TCP_NOPUSH
+# define HAVE_TCP_BUFFERING
+# define TCP_CORK TCP_NOPUSH
+# endif
+#endif
+
+
+#ifdef HAVE_TCP_BUFFERING
+static unsigned on = 1, off = 0;
+void buffer_output(void) {
+ struct CitContext *ctx = MyContext();
+ setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
+ ctx->buffering = 1;
+}
+
+void unbuffer_output(void) {
+ struct CitContext *ctx = MyContext();
+ setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
+ ctx->buffering = 0;
+}
+
+void flush_output(void) {
+ struct CitContext *ctx = MyContext();
+ setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
+ setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
+}
+#else
void buffer_output(void) {
if (CC->buffering == 0) {
CC->buffering = 1;
}
}
-/*
- * flush_output() ... dump out all that output we've been buffering.
- */
void flush_output(void) {
if (CC->buffering == 1) {
client_write(CC->output_buffer, CC->buffer_len);
}
}
-/*
- * unbuffer_output() ... stop buffering output.
- */
void unbuffer_output(void) {
if (CC->buffering == 1) {
CC->buffering = 0;
CC->output_buffer = NULL;
}
}
+#endif
sock = CC->client_socket;
}
+#ifndef HAVE_TCP_BUFFERING
/* If we're buffering for later, do that now. */
if (CC->buffering) {
old_buffer_len = CC->buffer_len;
memcpy(&CC->output_buffer[old_buffer_len], buf, nbytes);
return;
}
+#endif
/* Ok, at this point we're not buffering. Go ahead and write. */