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

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. engine.h
  5. Abstract:
  6. The public definition of HTTP protocol interfaces.
  7. Author:
  8. Michael Courage (mcourage) 17-Sep-1999
  9. Revision History:
  10. --*/
  11. #ifndef _ENGINE_H_
  12. #define _ENGINE_H_
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. typedef enum _UL_CONN_HDR
  17. {
  18. ConnHdrNone,
  19. ConnHdrClose,
  20. ConnHdrKeepAlive,
  21. ConnHdrMax
  22. } UL_CONN_HDR, *PUL_CONN_HDR;
  23. __inline
  24. UL_CONN_HDR
  25. FASTCALL
  26. UlChooseConnectionHeader(
  27. IN HTTP_VERSION Version,
  28. IN BOOLEAN Disconnect
  29. )
  30. {
  31. UL_CONN_HDR ConnHeader;
  32. //
  33. // Sanity check
  34. //
  35. PAGED_CODE();
  36. ConnHeader = ConnHdrNone;
  37. if (Disconnect) {
  38. if (HTTP_GREATER_EQUAL_VERSION(Version, 1, 0) || HTTP_EQUAL_VERSION(Version, 0, 0)) {
  39. //
  40. // Connection: close
  41. //
  42. ConnHeader = ConnHdrClose;
  43. }
  44. } else {
  45. if (HTTP_EQUAL_VERSION(Version, 1, 0)) {
  46. //
  47. // Connection: keep-alive
  48. //
  49. ConnHeader = ConnHdrKeepAlive;
  50. }
  51. }
  52. return ConnHeader;
  53. }
  54. __inline
  55. BOOLEAN
  56. FASTCALL
  57. UlCheckDisconnectInfo(
  58. IN PUL_INTERNAL_REQUEST pRequest
  59. )
  60. {
  61. BOOLEAN Disconnect;
  62. //
  63. // Sanity check
  64. //
  65. PAGED_CODE();
  66. ASSERT( UL_IS_VALID_INTERNAL_REQUEST( pRequest ) );
  67. if (
  68. //
  69. // pre-version 1.0
  70. //
  71. (HTTP_LESS_VERSION(pRequest->Version, 1, 0)) ||
  72. //
  73. // or version 1.0 with no Connection: Keep-Alive
  74. // CODEWORK: and no Keep-Alive header
  75. //
  76. (HTTP_EQUAL_VERSION(pRequest->Version, 1, 0) &&
  77. (pRequest->HeaderValid[HttpHeaderConnection] == FALSE ||
  78. !(pRequest->Headers[HttpHeaderConnection].HeaderLength == 10 &&
  79. (_stricmp(
  80. (const char*) pRequest->Headers[HttpHeaderConnection].pHeader,
  81. "keep-alive"
  82. ) == 0)))) ||
  83. //
  84. // or version 1.1 with a Connection: close
  85. // CODEWORK: move to parser or just make better in general..
  86. //
  87. (HTTP_EQUAL_VERSION(pRequest->Version, 1, 1) &&
  88. pRequest->HeaderValid[HttpHeaderConnection] &&
  89. pRequest->Headers[HttpHeaderConnection].HeaderLength == 5 &&
  90. _stricmp((const char*) pRequest->Headers[HttpHeaderConnection].pHeader, "close") == 0)
  91. )
  92. {
  93. Disconnect = TRUE;
  94. } else {
  95. Disconnect = FALSE;
  96. }
  97. return Disconnect;
  98. }
  99. __inline
  100. NTSTATUS
  101. FASTCALL
  102. UlCheckProtocolCompliance(
  103. IN PUL_HTTP_CONNECTION pConnection,
  104. IN PUL_INTERNAL_REQUEST pRequest
  105. )
  106. {
  107. NTSTATUS Status = STATUS_SUCCESS;
  108. //
  109. // Sanity check
  110. //
  111. PAGED_CODE();
  112. ASSERT( UL_IS_VALID_HTTP_CONNECTION(pConnection) );
  113. ASSERT( UL_IS_VALID_INTERNAL_REQUEST(pRequest) );
  114. //
  115. // check for entity body. TRACE is not allowed
  116. // to have a body.
  117. //
  118. if ((pRequest->ParseState != ParseDoneState)
  119. && ((pRequest->Verb == HttpVerbTRACE)
  120. || (pRequest->Verb == HttpVerbTRACK)))
  121. {
  122. Status = STATUS_INVALID_PARAMETER;
  123. }
  124. //
  125. // make sure that PUTs and POSTs do have a message body.
  126. // HTTP/1.0 requests must have a content length. HTTP/1.1 requests
  127. // must either be chunked or have a content length.
  128. //
  129. if (((pRequest->Verb == HttpVerbPUT)
  130. || (pRequest->Verb == HttpVerbPOST))
  131. && (!pRequest->HeaderValid[HttpHeaderContentLength])
  132. && ((HTTP_LESS_VERSION(pRequest->Version, 1, 1)) ||
  133. !pRequest->Chunked))
  134. {
  135. pRequest->ErrorCode = UlErrorContentLength;
  136. Status = STATUS_INVALID_PARAMETER;
  137. }
  138. //
  139. // 1.1 requests MUST have a host header
  140. // should we be checking >= UlHttpVersion11?
  141. //
  142. if ((HTTP_EQUAL_VERSION(pRequest->Version, 1, 1))
  143. && (!pRequest->HeaderValid[HttpHeaderHost]))
  144. {
  145. Status = STATUS_INVALID_PARAMETER;
  146. }
  147. //
  148. // If the major version is greater than 1, fail.
  149. //
  150. if (HTTP_GREATER_EQUAL_VERSION(pRequest->Version, 2, 0))
  151. {
  152. pRequest->ErrorCode = UlErrorVersion;
  153. Status = STATUS_INVALID_PARAMETER;
  154. }
  155. return Status;
  156. }
  157. __inline
  158. BOOLEAN
  159. FASTCALL
  160. UlNeedToGenerateContentLength(
  161. IN HTTP_VERB Verb,
  162. IN USHORT StatusCode,
  163. IN ULONG Flags
  164. )
  165. {
  166. //
  167. // Fast path: If there is more data on the way, then don't generate
  168. // the header.
  169. //
  170. if ((Flags & HTTP_SEND_RESPONSE_FLAG_MORE_DATA) != 0)
  171. {
  172. return FALSE;
  173. }
  174. //
  175. // RFC2616 section 4.3.
  176. //
  177. if (((StatusCode / 100) == 1) || // 1xx (informational)
  178. (StatusCode == 204) || // 204 (no content)
  179. (StatusCode == 304)) // 304 (not modified)
  180. {
  181. return FALSE;
  182. }
  183. if (Verb == HttpVerbHEAD)
  184. {
  185. return FALSE;
  186. }
  187. //
  188. // Otherwise, we can generate a content-length header.
  189. //
  190. return TRUE;
  191. }
  192. #ifdef __cplusplus
  193. }; // extern "C"
  194. #endif
  195. #endif // _ENGINE_H_