Source code of Windows XP (NT5)
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

/*++
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_