mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
5.0 KiB
250 lines
5.0 KiB
/*++
|
|
|
|
Copyright (c) 1999-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
engine.h
|
|
|
|
Abstract:
|
|
|
|
The public definition of HTTP protocol interfaces.
|
|
|
|
Author:
|
|
|
|
Michael Courage (mcourage) 17-Sep-1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#ifndef _ENGINE_H_
|
|
#define _ENGINE_H_
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
typedef enum _UL_CONN_HDR
|
|
{
|
|
ConnHdrNone,
|
|
ConnHdrClose,
|
|
ConnHdrKeepAlive,
|
|
|
|
ConnHdrMax
|
|
|
|
} UL_CONN_HDR, *PUL_CONN_HDR;
|
|
|
|
|
|
__inline
|
|
UL_CONN_HDR
|
|
FASTCALL
|
|
UlChooseConnectionHeader(
|
|
IN HTTP_VERSION Version,
|
|
IN BOOLEAN Disconnect
|
|
)
|
|
{
|
|
UL_CONN_HDR ConnHeader;
|
|
|
|
//
|
|
// Sanity check
|
|
//
|
|
PAGED_CODE();
|
|
|
|
ConnHeader = ConnHdrNone;
|
|
|
|
if (Disconnect) {
|
|
if (HTTP_GREATER_EQUAL_VERSION(Version, 1, 0) || HTTP_EQUAL_VERSION(Version, 0, 0)) {
|
|
//
|
|
// Connection: close
|
|
//
|
|
ConnHeader = ConnHdrClose;
|
|
}
|
|
} else {
|
|
if (HTTP_EQUAL_VERSION(Version, 1, 0)) {
|
|
//
|
|
// Connection: keep-alive
|
|
//
|
|
ConnHeader = ConnHdrKeepAlive;
|
|
}
|
|
}
|
|
|
|
return ConnHeader;
|
|
}
|
|
|
|
|
|
__inline
|
|
BOOLEAN
|
|
FASTCALL
|
|
UlCheckDisconnectInfo(
|
|
IN PUL_INTERNAL_REQUEST pRequest
|
|
)
|
|
{
|
|
BOOLEAN Disconnect;
|
|
|
|
//
|
|
// Sanity check
|
|
//
|
|
PAGED_CODE();
|
|
ASSERT( UL_IS_VALID_INTERNAL_REQUEST( pRequest ) );
|
|
|
|
if (
|
|
//
|
|
// pre-version 1.0
|
|
//
|
|
|
|
(HTTP_LESS_VERSION(pRequest->Version, 1, 0)) ||
|
|
|
|
//
|
|
// or version 1.0 with no Connection: Keep-Alive
|
|
// CODEWORK: and no Keep-Alive header
|
|
//
|
|
|
|
(HTTP_EQUAL_VERSION(pRequest->Version, 1, 0) &&
|
|
(pRequest->HeaderValid[HttpHeaderConnection] == FALSE ||
|
|
!(pRequest->Headers[HttpHeaderConnection].HeaderLength == 10 &&
|
|
(_stricmp(
|
|
(const char*) pRequest->Headers[HttpHeaderConnection].pHeader,
|
|
"keep-alive"
|
|
) == 0)))) ||
|
|
|
|
//
|
|
// or version 1.1 with a Connection: close
|
|
// CODEWORK: move to parser or just make better in general..
|
|
//
|
|
|
|
(HTTP_EQUAL_VERSION(pRequest->Version, 1, 1) &&
|
|
pRequest->HeaderValid[HttpHeaderConnection] &&
|
|
pRequest->Headers[HttpHeaderConnection].HeaderLength == 5 &&
|
|
_stricmp((const char*) pRequest->Headers[HttpHeaderConnection].pHeader, "close") == 0)
|
|
)
|
|
{
|
|
Disconnect = TRUE;
|
|
} else {
|
|
Disconnect = FALSE;
|
|
}
|
|
|
|
return Disconnect;
|
|
}
|
|
|
|
|
|
__inline
|
|
NTSTATUS
|
|
FASTCALL
|
|
UlCheckProtocolCompliance(
|
|
IN PUL_HTTP_CONNECTION pConnection,
|
|
IN PUL_INTERNAL_REQUEST pRequest
|
|
)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
//
|
|
// Sanity check
|
|
//
|
|
PAGED_CODE();
|
|
ASSERT( UL_IS_VALID_HTTP_CONNECTION(pConnection) );
|
|
ASSERT( UL_IS_VALID_INTERNAL_REQUEST(pRequest) );
|
|
|
|
//
|
|
// check for entity body. TRACE is not allowed
|
|
// to have a body.
|
|
//
|
|
if ((pRequest->ParseState != ParseDoneState)
|
|
&& ((pRequest->Verb == HttpVerbTRACE)
|
|
|| (pRequest->Verb == HttpVerbTRACK)))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
//
|
|
// make sure that PUTs and POSTs do have a message body.
|
|
// HTTP/1.0 requests must have a content length. HTTP/1.1 requests
|
|
// must either be chunked or have a content length.
|
|
//
|
|
if (((pRequest->Verb == HttpVerbPUT)
|
|
|| (pRequest->Verb == HttpVerbPOST))
|
|
&& (!pRequest->HeaderValid[HttpHeaderContentLength])
|
|
&& ((HTTP_LESS_VERSION(pRequest->Version, 1, 1)) ||
|
|
!pRequest->Chunked))
|
|
{
|
|
pRequest->ErrorCode = UlErrorContentLength;
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// 1.1 requests MUST have a host header
|
|
// should we be checking >= UlHttpVersion11?
|
|
//
|
|
if ((HTTP_EQUAL_VERSION(pRequest->Version, 1, 1))
|
|
&& (!pRequest->HeaderValid[HttpHeaderHost]))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// If the major version is greater than 1, fail.
|
|
//
|
|
|
|
if (HTTP_GREATER_EQUAL_VERSION(pRequest->Version, 2, 0))
|
|
{
|
|
pRequest->ErrorCode = UlErrorVersion;
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
__inline
|
|
BOOLEAN
|
|
FASTCALL
|
|
UlNeedToGenerateContentLength(
|
|
IN HTTP_VERB Verb,
|
|
IN USHORT StatusCode,
|
|
IN ULONG Flags
|
|
)
|
|
{
|
|
//
|
|
// Fast path: If there is more data on the way, then don't generate
|
|
// the header.
|
|
//
|
|
|
|
if ((Flags & HTTP_SEND_RESPONSE_FLAG_MORE_DATA) != 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// RFC2616 section 4.3.
|
|
//
|
|
|
|
if (((StatusCode / 100) == 1) || // 1xx (informational)
|
|
(StatusCode == 204) || // 204 (no content)
|
|
(StatusCode == 304)) // 304 (not modified)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (Verb == HttpVerbHEAD)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Otherwise, we can generate a content-length header.
|
|
//
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}; // extern "C"
|
|
#endif
|
|
|
|
#endif // _ENGINE_H_
|
|
|