You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by rj...@apache.org on 2008/09/27 21:50:29 UTC
svn commit: r699727 -
/tomcat/connectors/branches/other/jk_isapi_plugin_chunked/jk/native/iis/jk_isapi_plugin.c
Author: rjung
Date: Sat Sep 27 12:50:29 2008
New Revision: 699727
URL: http://svn.apache.org/viewvc?rev=699727&view=rev
Log:
Part 2 of chunked encoding: Further preparations
but do not actually chunk.
- Add enable_chunked_encoding config property
- Add done() method. Implementation needs to be
checked, but at the moment it is not really used
because we do not yet detect chunking.
- introduce new helper function isapi_write_client
which is almost the same as the inner loop in the
existing write(), but will be used multiple times
once we really do chunking.
CAUTION: WriteClient in the new function sets
dwSync=HSE_IO_SYNC. Before it was "0" in write().
MSDN says, only SYNC and ASYNC are allowed and
debug output shows, those values are 1 and 2.
We use "0" in three other places we might want
to switch to HSE_IO_SYNC?
Modified:
tomcat/connectors/branches/other/jk_isapi_plugin_chunked/jk/native/iis/jk_isapi_plugin.c
Modified: tomcat/connectors/branches/other/jk_isapi_plugin_chunked/jk/native/iis/jk_isapi_plugin.c
URL: http://svn.apache.org/viewvc/tomcat/connectors/branches/other/jk_isapi_plugin_chunked/jk/native/iis/jk_isapi_plugin.c?rev=699727&r1=699726&r2=699727&view=diff
==============================================================================
--- tomcat/connectors/branches/other/jk_isapi_plugin_chunked/jk/native/iis/jk_isapi_plugin.c (original)
+++ tomcat/connectors/branches/other/jk_isapi_plugin_chunked/jk/native/iis/jk_isapi_plugin.c Sat Sep 27 12:50:29 2008
@@ -116,6 +116,7 @@
#endif
#define REJECT_UNSAFE_TAG ("reject_unsafe")
#define WATCHDOG_INTERVAL_TAG ("watchdog_interval")
+#define ENABLE_CHUNKED_ENCODING_TAG ("enable_chunked_encoding")
#define TRANSLATE_HEADER ("Translate:")
#define TRANSLATE_HEADER_NAME ("Translate")
@@ -125,6 +126,10 @@
#define CRLF ("\r\n")
#define CRLF_LEN (2)
+/* Transfer-Encoding: chunked content trailer */
+#define CHUNKED_ENCODING_TRAILER ("0\r\n\r\n")
+#define CHUNKED_ENCODING_TRAILER_LEN (5)
+
#define BAD_REQUEST -1
#define BAD_PATH -2
#define MAX_SERVERNAME 128
@@ -216,6 +221,9 @@
#ifndef AUTOMATIC_AUTH_NOTIFICATION
static int use_auth_notification_flags = 1;
#endif
+/* Whether chunked encoding has been enabled in the settings */
+static int chunked_encoding_enabled = JK_FALSE;
+
static int reject_unsafe = 0;
static int watchdog_interval = 0;
static HANDLE watchdog_handle = NULL;
@@ -235,6 +243,7 @@
jk_pool_t p;
unsigned int bytes_read_so_far;
+ int chunk_content; /* Whether we're responding with Transfer-Encoding: chunked content */
LPEXTENSION_CONTROL_BLOCK lpEcb;
};
@@ -265,6 +274,8 @@
static int JK_METHOD write(jk_ws_service_t *s, const void *b, unsigned int l);
+static int JK_METHOD done(jk_ws_service_t *s);
+
static int init_ws_service(isapi_private_data_t * private_data,
jk_ws_service_t *s, char **worker_name);
@@ -764,37 +775,136 @@
return JK_FALSE;
}
+/*
+ * Writes a buffer to the ISAPI response.
+ */
+static int isapi_write_client(isapi_private_data_t *p, const char *buf, unsigned int write_length)
+{
+ unsigned int written = 0;
+ DWORD try_to_write = 0;
+
+ JK_TRACE_ENTER(logger);
+
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "Writing %d bytes of data to client", write_length);
+
+ while (written < write_length) {
+ try_to_write = write_length - written;
+ if (!p->lpEcb->WriteClient(p->lpEcb->ConnID,
+ (LPVOID)(buf + written), &try_to_write, HSE_IO_SYNC)) {
+ jk_log(logger, JK_LOG_ERROR,
+ "WriteClient failed with %d (0x%08x)", GetLastError(), GetLastError());
+ JK_TRACE_EXIT(logger);
+ return JK_FALSE;
+ }
+ written += try_to_write;
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "Wrote %d bytes of data successfully", try_to_write);
+ }
+ JK_TRACE_EXIT(logger);
+ return JK_TRUE;
+}
+
static int JK_METHOD write(jk_ws_service_t *s, const void *b, unsigned int l)
{
JK_TRACE_ENTER(logger);
+ if (!l) {
+ JK_TRACE_EXIT(logger);
+ return JK_TRUE;
+ }
+
if (s && s->ws_private && b) {
isapi_private_data_t *p = s->ws_private;
+ const char *buf = (const char *)b;
- if (l) {
- unsigned int written = 0;
- char *buf = (char *)b;
+ if (!p) {
+ JK_TRACE_EXIT(logger);
+ return JK_FALSE;
+ }
- if (!s->response_started) {
- start_response(s, 200, NULL, NULL, NULL, 0);
- }
+ if (!s->response_started) {
+ start_response(s, 200, NULL, NULL, NULL, 0);
+ }
+
+ if (isapi_write_client(p, buf, l) == JK_FALSE) {
+ JK_TRACE_EXIT(logger);
+ return JK_FALSE;
+ }
+
+ JK_TRACE_EXIT(logger);
+ return JK_TRUE;
+
+ }
+
+ JK_LOG_NULL_PARAMS(logger);
+ JK_TRACE_EXIT(logger);
+ return JK_FALSE;
+}
- while (written < l) {
- DWORD try_to_write = l - written;
- if (!p->lpEcb->WriteClient(p->lpEcb->ConnID,
- buf + written, &try_to_write, 0)) {
+/**
+ * In the case of a Transfer-Encoding: chunked response, this will write the terminator chunk.
+ */
+static int JK_METHOD done(jk_ws_service_t *s)
+{
+ JK_TRACE_ENTER(logger);
+
+ if (s && s->ws_private) {
+ isapi_private_data_t *p = s->ws_private;
+
+ if (p->chunk_content == JK_FALSE) {
+ JK_TRACE_EXIT(logger);
+ return JK_TRUE;
+ }
+
+ /* Write last chunk + terminator */
+ if (iis_info.major >= 6) {
+ HSE_RESPONSE_VECTOR response_vector;
+ HSE_VECTOR_ELEMENT response_elements[1];
+
+ response_elements[0].ElementType = HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER;
+ response_elements[0].pvContext = CHUNKED_ENCODING_TRAILER;
+ response_elements[0].cbOffset = 0;
+ response_elements[0].cbSize = CHUNKED_ENCODING_TRAILER_LEN;
+
+ /* HSE_IO_FINAL_SEND lets IIS process the response to the client before we return */
+ response_vector.dwFlags = HSE_IO_SYNC | HSE_IO_FINAL_SEND;
+ response_vector.pszStatus = NULL;
+ response_vector.pszHeaders = NULL;
+ response_vector.nElementCount = 1;
+ response_vector.lpElementArray = response_elements;
+
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG,
+ "Using vector write to terminate chunk encoded response.");
+
+ if (!p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID,
+ HSE_REQ_VECTOR_SEND,
+ &response_vector,
+ (LPDWORD)NULL,
+ (LPDWORD)NULL)) {
jk_log(logger, JK_LOG_ERROR,
- "WriteClient failed with %d (0x%08x)", GetLastError(), GetLastError());
+ "Vector termination of chunk encoded response failed with %d (0x%08x)",
+ GetLastError(), GetLastError());
JK_TRACE_EXIT(logger);
return JK_FALSE;
- }
- written += try_to_write;
+ }
+ }
+ else {
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "Terminating chunk encoded response");
+
+ if (!isapi_write_client(p, CHUNKED_ENCODING_TRAILER, CHUNKED_ENCODING_TRAILER_LEN)) {
+ jk_log(logger, JK_LOG_ERROR,
+ "WriteClient for chunked response terminator failed with %d (0x%08x)",
+ GetLastError(), GetLastError());
+ JK_TRACE_EXIT(logger);
+ return JK_FALSE;
}
}
JK_TRACE_EXIT(logger);
return JK_TRUE;
-
}
JK_LOG_NULL_PARAMS(logger);
@@ -1535,6 +1645,7 @@
private_data.bytes_read_so_far = 0;
private_data.lpEcb = lpEcb;
+ private_data.chunk_content = JK_FALSE;
s.ws_private = &private_data;
s.pool = &private_data.p;
@@ -1772,6 +1883,7 @@
jk_log(logger, JK_LOG_DEBUG, "Using rewrite rule file %s.",
rewrite_rule_file);
jk_log(logger, JK_LOG_DEBUG, "Using uri select %d.", uri_select_option);
+ jk_log(logger, JK_LOG_DEBUG, "Using%s chunked encoding.", (chunked_encoding_enabled ? "" : " no"));
jk_log(logger, JK_LOG_DEBUG, "Using notification event %s (0x%08x)",
(iis_info.filter_notify_event == SF_NOTIFY_AUTH_COMPLETE) ?
@@ -1984,6 +2096,8 @@
#endif
reject_unsafe = get_config_bool(src, REJECT_UNSAFE_TAG, JK_FALSE);
watchdog_interval = get_config_int(src, WATCHDOG_INTERVAL_TAG, 0);
+ chunked_encoding_enabled = get_config_bool(src, ENABLE_CHUNKED_ENCODING_TAG, JK_FALSE);
+
if (using_ini_file) {
jk_map_free(&map);
}
@@ -2089,6 +2203,7 @@
s->start_response = start_response;
s->read = read;
s->write = write;
+ s->done = done;
if (!(huge_buf = jk_pool_alloc(&private_data->p, MAX_PACKET_SIZE))) {
JK_TRACE_EXIT(logger);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org