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