209 lines
8.2 KiB
Plaintext
209 lines
8.2 KiB
Plaintext
|
Random thoughts, miscellaneous ramblings -- keithmo, 11/30/98
|
||
|
|
||
|
|
||
|
1. The user-mode interface to the open-file-handle-cache is problematic,
|
||
|
especially regarding thread security context (impersonation). We can't
|
||
|
use the IIS-style "match-the-thread-token-handle" technique, as the
|
||
|
cache is accessible from multiple processes which may (probably will)
|
||
|
have different handle values for the same security token. I suspect that
|
||
|
we'd need to actually snapshot the security token whenever an new entry
|
||
|
is inserted into the cache, then compare that snapshot with the incoming
|
||
|
token when testing for a cache hit. Ugh.
|
||
|
|
||
|
I say we yank the user-mode interface.
|
||
|
|
||
|
|
||
|
2. The current thinking for the response-cache has "weak" references to
|
||
|
the open-file-handle-cache. This allows open-file-handle-cache entries
|
||
|
to come & go independently of the response-cache. I think we could
|
||
|
simplify the implementation somewhat by "strengthening" this reference
|
||
|
so that a response-cache entry becomes invalidated whenever any of
|
||
|
the referenced open-file-handle-cache entries are invalidated. This
|
||
|
could be useful as a cheap & easy filesystem "change notify" mechanism
|
||
|
for user-mode worker processes. (See below.)
|
||
|
|
||
|
|
||
|
3. Along the same lines as #2, it may be useful to allow "zero-length"
|
||
|
byte ranges in UL_HTTP_RESPONSE structures. This would allow user-mode
|
||
|
code to establish a relationship between a response-cache entry and
|
||
|
an open-file-handle-cache entry solely for the purposes of invalidation.
|
||
|
|
||
|
Imagine a response-cache entry representing the dynamic output from a
|
||
|
.XSP file. The UL_HTTP_RESPONSE structure representing this response
|
||
|
could contain a zero-length byte range referring to the source .XSP
|
||
|
file. If the .XSP file was flushed from the open-file-handle-cache
|
||
|
(say, due to an oplock break) then the user-mode process would receive
|
||
|
a "normal" cache miss notification.
|
||
|
|
||
|
|
||
|
4. It may be useful to provide a "notification type" value in the
|
||
|
UL_HTTP_REQUEST returned by the UlReceiveHttpRequest() API. This
|
||
|
value would give a "hint" indication for the reason the request
|
||
|
was passed up to user-mode. Possible reasons include:
|
||
|
|
||
|
response-cache miss - The incoming URL was *not* present in
|
||
|
the response-cache.
|
||
|
|
||
|
open-file-handle-cache miss - The incoming URL *was* present
|
||
|
in the response-cache, but one or more of the referenced
|
||
|
files were *not* present in the open-file-handle-cache.
|
||
|
|
||
|
cache policy miss - The incoming URL *was* present in the
|
||
|
response-cache, but the cache-control information set on
|
||
|
the cache entry was incompatible with the incoming request.
|
||
|
|
||
|
security - The incoming URL *was* present in the response-cache,
|
||
|
but the cache entry is configured for a security provider
|
||
|
requring user-mode intervention.
|
||
|
|
||
|
etc, etc, etc
|
||
|
|
||
|
|
||
|
5. Need to add a UlSendHttpResponseFromCache() API. This should take a
|
||
|
UL_HTTP_REQUEST structure as returned by UlReceiveHttpRequest(), hit
|
||
|
the response-cache, and send the cached response if successful. If
|
||
|
the URL is not in the response-cache, then API fails with a
|
||
|
distinguished error value.
|
||
|
|
||
|
|
||
|
6. Probably need a UlReceiveEntityBody() API to read the "leftover" part
|
||
|
of the entity body that could not fit into the original request
|
||
|
buffer.
|
||
|
|
||
|
|
||
|
7. User-mode worker processes issue one or more UlReceiveHttpRequest()
|
||
|
APIs that pend if necessary, waiting for incoming requests. What
|
||
|
happens if the supplied buffer is too small for the incoming request
|
||
|
header?
|
||
|
|
||
|
For each *process*, UL needs a separate queue of pending requests. This
|
||
|
queue represents the set of requests for which either a) an attempt was
|
||
|
made to deliver the request to user-mode but the supplied request buffer
|
||
|
was too small, or b) unread entity body data is remaining.
|
||
|
|
||
|
|
||
|
8. Need a mechanism to notify user-mode whenever an established connection
|
||
|
is disconnected. This is especially useful for worker-processes that
|
||
|
support the old ISAPI filter mechanism.
|
||
|
|
||
|
Unfortunately, we cannot leverage the existing UlReadHttpRequest()
|
||
|
API for these notifications. Consider a Web Garden in which multiple
|
||
|
processes receive requests for a single connection. Which process
|
||
|
gets the notification? The first? The last? All of them?
|
||
|
|
||
|
We'll probably need a separate API for disconnect notifications.
|
||
|
|
||
|
|
||
|
9. With the new handle-based app pool open/creation APIs, UL needs
|
||
|
a reliable way to distinguish three separate open modes:
|
||
|
|
||
|
1. Open a control channel
|
||
|
2. Create a new app pool
|
||
|
3. Open an existing app pool
|
||
|
|
||
|
The "control channel" cases can be distinguished from the "app pool"
|
||
|
cases by the presence of the filename buffer in the FILE_OBJECT. If
|
||
|
there is a name, it's an app pool, if not, it's a control channel.
|
||
|
|
||
|
Distinguishing app pool "create" from "open" is a bit trickier. Some
|
||
|
spelunking uncovered a way: The Disposition parameter to NtCreateFile()
|
||
|
is propagated in the IRP_MJ_CREATE IRP, stuffed into the high byte of
|
||
|
IO_STACK_LOCATION.Parameters.Create.Options.
|
||
|
|
||
|
The creation becomes:
|
||
|
|
||
|
if (pIrpSp->FileObject->FileName.Buffer == NULL)
|
||
|
{
|
||
|
//
|
||
|
// Open a control channel.
|
||
|
//
|
||
|
|
||
|
status = UlpOpenControlChannel( pIrp, pIrpSp );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// IO passes the creation disposition in the high byte of
|
||
|
// the Options field. Extract & decode it.
|
||
|
//
|
||
|
|
||
|
switch ((pIrpSp->Parameters.Create.Options >> 24) & 0xFF)
|
||
|
{
|
||
|
case FILE_CREATE:
|
||
|
//
|
||
|
// Create a new app pool. This will fail if the app pool
|
||
|
// already exists.
|
||
|
//
|
||
|
|
||
|
status = UlpCreateAppPool( pIrp, pIrpSp );
|
||
|
break;
|
||
|
|
||
|
case FILE_OPEN:
|
||
|
//
|
||
|
// Open an existing app pool. This will fail if the app
|
||
|
// pool does not already exist.
|
||
|
//
|
||
|
|
||
|
status = UlpOpenAppPool( pIrp, pIrpSp );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
//
|
||
|
// No need to be flexible here. Fail the request.
|
||
|
//
|
||
|
|
||
|
status = STATUS_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
10. We still need to think carefully through the whole URL canonicalization
|
||
|
mess. How do we canonicalize an incoming URL if there's no host
|
||
|
header in the request?
|
||
|
|
||
|
Henry has suggested a separate IP-address-to-host-name lookaside
|
||
|
table in UL, configured by user-mode (probably the application
|
||
|
manager).
|
||
|
|
||
|
|
||
|
11. We still need to define the exact contents of the UL_CACHE_POLICY
|
||
|
structure (the one that defines the caching characteristis of
|
||
|
a specific HTTP response).
|
||
|
|
||
|
|
||
|
12. The opaque ID package needs refinement. See objtable.c for one
|
||
|
proposed solution.
|
||
|
|
||
|
|
||
|
13. UL needs a ton of bug fixes on its disconnect logic. The logic is
|
||
|
related to the HTTP protocol version, the transfer encoding, and
|
||
|
whether or not the data is streamed from user-mode:
|
||
|
|
||
|
Version Chunked Non-Chunked
|
||
|
~~~~~~~ ~~~~~~~ Non-Streamed Streamed
|
||
|
~~~~~~~~~~~~ ~~~~~~~~
|
||
|
|
||
|
0.9 N/A CLOSE CLOSE
|
||
|
|
||
|
1.0 N/A CLOSE IF !PC CLOSE
|
||
|
|
||
|
1.1 SEND EMPTY CHUNK, CLOSE IF !PC CLOSE
|
||
|
CLOSE IF !PC
|
||
|
|
||
|
|
||
|
14. We currently use Named Pipes (and MCourage's most-excellent IPM
|
||
|
wrapper) for IPC between WAS and WP. This works great under NT,
|
||
|
but Named Pipes are not supported on Win9x or WinCE.
|
||
|
|
||
|
We could use anonymous pipes (via the CreatePipe() API). However,
|
||
|
while anonymous pipes ARE supported under WinNT and Win9x, they're
|
||
|
NOT supported under WinCE. This may not be a big deal (we probably
|
||
|
won't have a robust process model under WinCE anyway). A bigger
|
||
|
drawback to anonymous pipes is that they are synchronous only
|
||
|
(no overlapped I/O). Yuck.
|
||
|
|
||
|
After further investigation, it appears that we're almost totally
|
||
|
hozed when it comes to IPC on WinCE. As near as I can tell, the
|
||
|
only reasonable IPC mechanism available in WinCE is sockets...
|
||
|
|