Author: mturk
Date: Tue Nov 15 20:00:21 2011
New Revision: 1202402
URL: http://svn.apache.org/viewvc?rev=1202402&view=rev
Log:
Bail out early on invalid params. No functional change
Modified:
tomcat/jk/trunk/native/iis/jk_isapi_plugin.c
Modified: tomcat/jk/trunk/native/iis/jk_isapi_plugin.c
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/iis/jk_isapi_plugin.c?rev=1202402&r1=1202401&r2=1202402&view=diff
==============================================================================
--- tomcat/jk/trunk/native/iis/jk_isapi_plugin.c (original)
+++ tomcat/jk/trunk/native/iis/jk_isapi_plugin.c Tue Nov 15 20:00:21 2011
@@ -970,6 +970,9 @@ static int JK_METHOD start_response(jk_w
const char *const *header_values,
unsigned int num_of_headers)
{
+ int rv = JK_TRUE;
+ isapi_private_data_t *p;
+
JK_TRACE_ENTER(logger);
if (status < 100 || status > 1000) {
jk_log(logger, JK_LOG_ERROR,
@@ -978,285 +981,289 @@ static int JK_METHOD start_response(jk_w
JK_TRACE_EXIT(logger);
return JK_FALSE;
}
+ if (s == NULL || s->ws_private == NULL) {
+ JK_LOG_NULL_PARAMS(logger);
+ JK_TRACE_EXIT(logger);
+ return JK_FALSE;
+ }
+ p = s->ws_private;
- if (s && s->ws_private) {
- int rv = JK_TRUE;
- isapi_private_data_t *p = s->ws_private;
-
- /* If we use proxy error pages, still pass
- * through context headers needed for special status codes.
- */
- if (s->extension.use_server_error_pages &&
- status >= s->extension.use_server_error_pages) {
- if (status == JK_HTTP_UNAUTHORIZED) {
- int found = JK_FALSE;
- unsigned int h;
- for (h = 0; h < num_of_headers; h++) {
- if (!strcasecmp(header_names[h], "WWW-Authenticate")) {
- p->err_hdrs = jk_pool_strcatv(&p->p,
- "WWW-Authenticate:",
- header_values[h], CRLF, NULL);
- found = JK_TRUE;
- }
- }
- if (found == JK_FALSE) {
- jk_log(logger, JK_LOG_INFO,
- "origin server sent 401 without"
- " WWW-Authenticate header");
- }
+ /* If we use proxy error pages, still pass
+ * through context headers needed for special status codes.
+ */
+ if (s->extension.use_server_error_pages &&
+ status >= s->extension.use_server_error_pages) {
+ if (status == JK_HTTP_UNAUTHORIZED) {
+ int found = JK_FALSE;
+ unsigned int h;
+ for (h = 0; h < num_of_headers; h++) {
+ if (!strcasecmp(header_names[h], "WWW-Authenticate")) {
+ p->err_hdrs = jk_pool_strcatv(&p->p,
+ "WWW-Authenticate:",
+ header_values[h], CRLF, NULL);
+ found = JK_TRUE;
+ }
+ }
+ if (found == JK_FALSE) {
+ jk_log(logger, JK_LOG_INFO,
+ "origin server sent 401 without"
+ " WWW-Authenticate header");
}
- return JK_TRUE;
}
+ return JK_TRUE;
+ }
- if (!s->response_started) {
- char *status_str = NULL;
- char *headers_str = NULL;
- BOOL keep_alive = FALSE; /* Whether the downstream or us can
supply content length */
- BOOL rc;
- size_t i, len_of_headers = 0;
+ if (!s->response_started) {
+ char *status_str = NULL;
+ char *headers_str = NULL;
+ BOOL keep_alive = FALSE; /* Whether the downstream or us can
supply content length */
+ BOOL rc;
+ size_t i, len_of_headers = 0;
- s->response_started = JK_TRUE;
+ s->response_started = JK_TRUE;
- if (JK_IS_DEBUG_LEVEL(logger)) {
- jk_log(logger, JK_LOG_DEBUG, "Starting response for URI '%s'
(protocol %s)",
- s->req_uri, s->protocol);
- }
+ if (JK_IS_DEBUG_LEVEL(logger)) {
+ jk_log(logger, JK_LOG_DEBUG, "Starting response for URI '%s'
(protocol %s)",
+ s->req_uri, s->protocol);
+ }
- /*
- * Create the status line
- */
- if (!reason) {
- reason = status_reason(status);
- }
- status_str = (char *)malloc((6 + strlen(reason)));
- StringCbPrintf(status_str, 6 + strlen(reason), "%d %s", status,
reason);
+ /*
+ * Create the status line
+ */
+ if (!reason) {
+ reason = status_reason(status);
+ }
+ status_str = (char *)malloc((6 + strlen(reason)));
+ StringCbPrintf(status_str, 6 + strlen(reason), "%d %s", status,
reason);
- if (chunked_encoding_enabled) {
- /* Check if we've got an HTTP/1.1 response */
- if (!strcasecmp(s->protocol, "HTTP/1.1")) {
- keep_alive = TRUE;
- /* Chunking only when HTTP/1.1 client and enabled */
- p->chunk_content = JK_TRUE;
- }
+ if (chunked_encoding_enabled) {
+ /* Check if we've got an HTTP/1.1 response */
+ if (!strcasecmp(s->protocol, "HTTP/1.1")) {
+ keep_alive = TRUE;
+ /* Chunking only when HTTP/1.1 client and enabled */
+ p->chunk_content = JK_TRUE;
}
+ }
- /*
- * Create response headers string
- */
+ /*
+ * Create response headers string
+ */
- /* Calculate length of headers block */
- for (i = 0; i < num_of_headers; i++) {
- len_of_headers += strlen(header_names[i]);
- len_of_headers += strlen(header_values[i]);
- len_of_headers += 4; /* extra for colon, space and crlf */
- }
+ /* Calculate length of headers block */
+ for (i = 0; i < num_of_headers; i++) {
+ len_of_headers += strlen(header_names[i]);
+ len_of_headers += strlen(header_values[i]);
+ len_of_headers += 4; /* extra for colon, space and crlf */
+ }
- /*
- * Exclude status codes that MUST NOT include message bodies
- */
- if ((status == 204) || (status == 205) || (status == 304)) {
- p->chunk_content = JK_FALSE;
- /* Keep alive is still possible */
- if (JK_IS_DEBUG_LEVEL(logger))
- jk_log(logger, JK_LOG_DEBUG, "Response status %d implies
no message body", status );
- }
- if (p->chunk_content) {
- for (i = 0; i < num_of_headers; i++) {
- /* Check the downstream response to see whether
- * it's appropriate to chunk the response content
- * and whether it supports keeping the connection open.
-
- * This implements the rules for HTTP/1.1 message length
determination
- * with the exception of multipart/byteranges media types.
- *
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
- */
- if (!strcasecmp(CONTENT_LENGTH_HEADER_NAME,
header_names[i])) {
- p->chunk_content = JK_FALSE;
- if (JK_IS_DEBUG_LEVEL(logger))
- jk_log(logger, JK_LOG_DEBUG, "Response specifies
Content-Length" );
- }
- else if (!strcasecmp(CONNECTION_HEADER_NAME,
header_names[i])
- && !strcasecmp(CONNECTION_CLOSE_VALUE,
header_values[i])) {
- keep_alive = FALSE;
- p->chunk_content = JK_FALSE;
- if (JK_IS_DEBUG_LEVEL(logger))
- jk_log(logger, JK_LOG_DEBUG, "Response specifies
Connection: Close" );
- }
- else if (!strcasecmp(TRANSFER_ENCODING_HEADER_NAME,
header_names[i])
- && !strcasecmp(TRANSFER_ENCODING_IDENTITY_VALUE,
header_values[i])) {
- /* HTTP states that this must include 'chunked' as the
last value.
- * 'identity' is the same as absence of the header
*/
- p->chunk_content = JK_FALSE;
- if (JK_IS_DEBUG_LEVEL(logger))
- jk_log(logger, JK_LOG_DEBUG, "Response specifies
Transfer-Encoding" );
- }
+ /*
+ * Exclude status codes that MUST NOT include message bodies
+ */
+ if ((status == 204) || (status == 205) || (status == 304)) {
+ p->chunk_content = JK_FALSE;
+ /* Keep alive is still possible */
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "Response status %d implies no
message body", status );
+ }
+ if (p->chunk_content) {
+ for (i = 0; i < num_of_headers; i++) {
+ /* Check the downstream response to see whether
+ * it's appropriate to chunk the response content
+ * and whether it supports keeping the connection open.
+
+ * This implements the rules for HTTP/1.1 message length
determination
+ * with the exception of multipart/byteranges media types.
+ * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
+ */
+ if (!strcasecmp(CONTENT_LENGTH_HEADER_NAME, header_names[i])) {
+ p->chunk_content = JK_FALSE;
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "Response specifies
Content-Length" );
+ }
+ else if (!strcasecmp(CONNECTION_HEADER_NAME, header_names[i])
+ && !strcasecmp(CONNECTION_CLOSE_VALUE,
header_values[i])) {
+ keep_alive = FALSE;
+ p->chunk_content = JK_FALSE;
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "Response specifies
Connection: Close" );
+ }
+ else if (!strcasecmp(TRANSFER_ENCODING_HEADER_NAME,
header_names[i])
+ && !strcasecmp(TRANSFER_ENCODING_IDENTITY_VALUE,
header_values[i])) {
+ /* HTTP states that this must include 'chunked' as the
last value.
+ * 'identity' is the same as absence of the header */
+ p->chunk_content = JK_FALSE;
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "Response specifies
Transfer-Encoding" );
}
-
- /* Provide room in the buffer for the Transfer-Encoding header
if we use it. */
- len_of_headers +=
TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE_LEN + 2;
}
- /* Allocate and init the headers string */
- len_of_headers += 3; /* crlf and terminating null char */
- headers_str = (char *)malloc(len_of_headers);
- headers_str[0] = '\0';
+ /* Provide room in the buffer for the Transfer-Encoding header if
we use it. */
+ len_of_headers += TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE_LEN +
2;
+ }
- /* Copy headers into headers block for sending */
- for (i = 0; i < num_of_headers; i++) {
- StringCbCat(headers_str, len_of_headers, header_names[i]);
- StringCbCat(headers_str, len_of_headers, ": ");
- StringCbCat(headers_str, len_of_headers, header_values[i]);
- StringCbCat(headers_str, len_of_headers, CRLF);
- }
+ /* Allocate and init the headers string */
+ len_of_headers += 3; /* crlf and terminating null char */
+ headers_str = (char *)malloc(len_of_headers);
+ headers_str[0] = '\0';
- if (p->chunk_content) {
- /* Configure the response if chunked encoding is used */
- if (JK_IS_DEBUG_LEVEL(logger))
- jk_log(logger, JK_LOG_DEBUG, "Using Transfer-Encoding:
chunked");
+ /* Copy headers into headers block for sending */
+ for (i = 0; i < num_of_headers; i++) {
+ StringCbCat(headers_str, len_of_headers, header_names[i]);
+ StringCbCat(headers_str, len_of_headers, ": ");
+ StringCbCat(headers_str, len_of_headers, header_values[i]);
+ StringCbCat(headers_str, len_of_headers, CRLF);
+ }
- /** We will supply the transfer-encoding to allow IIS to keep
the connection open */
- keep_alive = TRUE;
+ if (p->chunk_content) {
+ /* Configure the response if chunked encoding is used */
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "Using Transfer-Encoding:
chunked");
- /* Indicate to the client that the content will be chunked
- - We've already reserved space for this */
- StringCbCat(headers_str, len_of_headers,
TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE);
- StringCbCat(headers_str, len_of_headers, CRLF);
- }
+ /** We will supply the transfer-encoding to allow IIS to keep the
connection open */
+ keep_alive = TRUE;
- /* Terminate the headers */
+ /* Indicate to the client that the content will be chunked
+ - We've already reserved space for this */
+ StringCbCat(headers_str, len_of_headers,
TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE);
StringCbCat(headers_str, len_of_headers, CRLF);
+ }
- if (JK_IS_DEBUG_LEVEL(logger))
- jk_log(logger, JK_LOG_DEBUG, "%ssing Keep-Alive", (keep_alive
? "U" : "Not u"));
+ /* Terminate the headers */
+ StringCbCat(headers_str, len_of_headers, CRLF);
- if (keep_alive) {
- HSE_SEND_HEADER_EX_INFO hi;
+ if (JK_IS_DEBUG_LEVEL(logger))
+ jk_log(logger, JK_LOG_DEBUG, "%ssing Keep-Alive", (keep_alive ?
"U" : "Not u"));
- /* Fill in the response */
- hi.pszStatus = status_str;
- hi.pszHeader = headers_str;
- hi.cchStatus = (DWORD)strlen(status_str);
- hi.cchHeader = (DWORD)strlen(headers_str);
+ if (keep_alive) {
+ HSE_SEND_HEADER_EX_INFO hi;
- /*
- * Using the extended form of the API means we have to get
this right,
- * i.e. IIS won't keep connections open if there's a
Content-Length and close them if there isn't.
- */
- hi.fKeepConn = keep_alive;
+ /* Fill in the response */
+ hi.pszStatus = status_str;
+ hi.pszHeader = headers_str;
+ hi.cchStatus = (DWORD)strlen(status_str);
+ hi.cchHeader = (DWORD)strlen(headers_str);
- /* Send the response to the client */
- rc = p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID,
-
HSE_REQ_SEND_RESPONSE_HEADER_EX,
- &hi,
- NULL, NULL);
- }
- else {
- DWORD status_str_len = (DWORD)strlen(status_str);
- /* Old style response - forces Connection: close if Tomcat
response doesn't
- specify necessary details to allow keep alive */
- rc = p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID,
-
HSE_REQ_SEND_RESPONSE_HEADER,
- status_str,
- &status_str_len,
- (LPDWORD)headers_str);
- }
+ /*
+ * Using the extended form of the API means we have to get this
right,
+ * i.e. IIS won't keep connections open if there's a
Content-Length and close them if there isn't.
+ */
+ hi.fKeepConn = keep_alive;
- if (!rc) {
- jk_log(logger, JK_LOG_ERROR,
- "HSE_REQ_SEND_RESPONSE_HEADER%s failed with error=%d
(0x%08x)",
- (keep_alive ? "_EX" : ""), GetLastError(),
GetLastError());
- rv = JK_FALSE;
- }
- if (headers_str)
- free(headers_str);
- if (status_str)
- free(status_str);
+ /* Send the response to the client */
+ rc = p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID,
+
HSE_REQ_SEND_RESPONSE_HEADER_EX,
+ &hi,
+ NULL, NULL);
+ }
+ else {
+ DWORD status_str_len = (DWORD)strlen(status_str);
+ /* Old style response - forces Connection: close if Tomcat
response doesn't
+ specify necessary details to allow keep alive */
+ rc = p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID,
+ HSE_REQ_SEND_RESPONSE_HEADER,
+ status_str,
+ &status_str_len,
+ (LPDWORD)headers_str);
}
- JK_TRACE_EXIT(logger);
- return rv;
- }
- JK_LOG_NULL_PARAMS(logger);
+ if (!rc) {
+ jk_log(logger, JK_LOG_ERROR,
+ "HSE_REQ_SEND_RESPONSE_HEADER%s failed with error=%d
(0x%08x)",
+ (keep_alive ? "_EX" : ""), GetLastError(), GetLastError());
+ rv = JK_FALSE;
+ }
+ if (headers_str)
+ free(headers_str);
+ if (status_str)
+ free(status_str);
+ }
JK_TRACE_EXIT(logger);
- return JK_FALSE;
+ return rv;
}
static int JK_METHOD iis_read(jk_ws_service_t *s,
- void *b, unsigned int l, unsigned int *a)
+ void *b, unsigned int l, unsigned int *a)
{
- JK_TRACE_ENTER(logger);
+ isapi_private_data_t *p;
- if (s && s->ws_private && b && a) {
- isapi_private_data_t *p = s->ws_private;
+ JK_TRACE_ENTER(logger);
+ if (s == NULL || s->ws_private == NULL) {
+ JK_LOG_NULL_PARAMS(logger);
+ JK_TRACE_EXIT(logger);
+ return JK_FALSE;
+ }
+ if (a == NULL || b == NULL) {
+ /* XXX: Do we really need those useless checks?
+ */
+ JK_LOG_NULL_PARAMS(logger);
+ JK_TRACE_EXIT(logger);
+ return JK_FALSE;
- if (JK_IS_DEBUG_LEVEL(logger)) {
- jk_log(logger, JK_LOG_DEBUG,
- "Preparing to read %d bytes. "
- "ECB reports %d bytes total, with %d available.",
- l, p->lpEcb->cbTotalBytes, p->lpEcb->cbAvailable);
- }
+ }
+ p = s->ws_private;
+ if (JK_IS_DEBUG_LEVEL(logger)) {
+ jk_log(logger, JK_LOG_DEBUG,
+ "Preparing to read %d bytes. "
+ "ECB reports %d bytes total, with %d available.",
+ l, p->lpEcb->cbTotalBytes, p->lpEcb->cbAvailable);
+ }
- *a = 0;
- if (l) {
- char *buf = b;
- DWORD already_read = p->lpEcb->cbAvailable - p->bytes_read_so_far;
+ *a = 0;
+ if (l) {
+ char *buf = b;
+ DWORD already_read = p->lpEcb->cbAvailable - p->bytes_read_so_far;
- if (already_read >= l) {
+ if (already_read >= l) {
+ if (JK_IS_DEBUG_LEVEL(logger)) {
+ jk_log(logger, JK_LOG_DEBUG,
+ "Already read %d bytes - supplying %d bytes from
buffer",
+ already_read, l);
+ }
+ memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far, l);
+ p->bytes_read_so_far += l;
+ *a = l;
+ }
+ else {
+ /*
+ * Try to copy what we already have
+ */
+ if (already_read > 0) {
if (JK_IS_DEBUG_LEVEL(logger)) {
jk_log(logger, JK_LOG_DEBUG,
- "Already read %d bytes - supplying %d bytes from
buffer",
- already_read, l);
- }
- memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far, l);
- p->bytes_read_so_far += l;
- *a = l;
- }
- else {
- /*
- * Try to copy what we already have
- */
- if (already_read > 0) {
- if (JK_IS_DEBUG_LEVEL(logger)) {
- jk_log(logger, JK_LOG_DEBUG,
- "Supplying %d bytes from buffer",
- already_read);
- }
- memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far,
+ "Supplying %d bytes from buffer",
already_read);
- buf += already_read;
- l -= already_read;
- p->bytes_read_so_far = p->lpEcb->cbAvailable;
-
- *a = already_read;
}
+ memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far,
+ already_read);
+ buf += already_read;
+ l -= already_read;
+ p->bytes_read_so_far = p->lpEcb->cbAvailable;
- /*
- * Now try to read from the client ...
- */
- if (JK_IS_DEBUG_LEVEL(logger)) {
- jk_log(logger, JK_LOG_DEBUG,
- "Attempting to read %d bytes from client", l);
- }
- if (p->lpEcb->ReadClient(p->lpEcb->ConnID, buf, &l)) {
- /* ReadClient will succeed with dwSize == 0 for last chunk
- if request chunk encoded */
- *a += l;
- }
- else {
- jk_log(logger, JK_LOG_ERROR,
- "ReadClient failed with %d (0x%08x)",
GetLastError(), GetLastError());
- JK_TRACE_EXIT(logger);
- return JK_FALSE;
- }
+ *a = already_read;
+ }
+
+ /*
+ * Now try to read from the client ...
+ */
+ if (JK_IS_DEBUG_LEVEL(logger)) {
+ jk_log(logger, JK_LOG_DEBUG,
+ "Attempting to read %d bytes from client", l);
+ }
+ if (p->lpEcb->ReadClient(p->lpEcb->ConnID, buf, &l)) {
+ /* ReadClient will succeed with dwSize == 0 for last chunk
+ if request chunk encoded */
+ *a += l;
+ }
+ else {
+ jk_log(logger, JK_LOG_ERROR,
+ "ReadClient 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);
JK_TRACE_EXIT(logger);
- return JK_FALSE;
+ return JK_TRUE;
}
/*
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]