1 use crate::{guid, Char16, Char8, Event, Guid, Ipv4Address, Ipv6Address, Status};
2 use core::ffi::c_void;
3 use core::fmt::{self, Debug, Formatter};
4 
5 #[derive(Debug)]
6 #[repr(C)]
7 pub struct HttpConfigData {
8     pub http_version: HttpVersion,
9     pub time_out_millisec: u32,
10     pub local_addr_is_ipv6: bool,
11     pub access_point: HttpAccessPoint,
12 }
13 
14 newtype_enum! {
15     pub enum HttpVersion: i32 => {
16         HTTP_VERSION_10 = 0,
17         HTTP_VERSION_11 = 1,
18         HTTP_VERSION_UNSUPPORTED = 2,
19     }
20 }
21 
22 #[derive(Debug)]
23 #[repr(C)]
24 pub struct HttpV4AccessPoint {
25     pub use_default_addr: bool,
26     pub local_address: Ipv4Address,
27     pub local_subnet: Ipv4Address,
28     pub local_port: u16,
29 }
30 
31 #[derive(Debug)]
32 #[repr(C)]
33 pub struct HttpV6AccessPoint {
34     pub local_address: Ipv6Address,
35     pub local_port: u16,
36 }
37 
38 #[repr(C)]
39 pub union HttpAccessPoint {
40     pub ipv4_node: *const HttpV4AccessPoint,
41     pub ipv6_node: *const HttpV6AccessPoint,
42 }
43 
44 impl Debug for HttpAccessPoint {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result45     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
46         // This is a union type, so we can't access the internal data.
47         f.debug_struct("HttpAccessPoint").finish()
48     }
49 }
50 
51 #[derive(Debug)]
52 #[repr(C)]
53 pub struct HttpToken {
54     pub event: Event,
55     pub status: Status,
56     pub message: *mut HttpMessage,
57 }
58 
59 #[derive(Debug)]
60 #[repr(C)]
61 pub struct HttpMessage {
62     pub data: HttpRequestOrResponse,
63     pub header_count: usize,
64     pub header: *mut HttpHeader,
65     pub body_length: usize,
66     pub body: *mut c_void,
67 }
68 
69 #[derive(Debug)]
70 #[repr(C)]
71 pub struct HttpRequestData {
72     pub method: HttpMethod,
73     pub url: *const Char16,
74 }
75 
76 newtype_enum! {
77     pub enum HttpMethod: i32 => {
78         GET     = 0,
79         POST    = 1,
80         PATCH   = 2,
81         OPTIONS = 3,
82         CONNECT = 4,
83         HEAD    = 5,
84         PUT     = 6,
85         DELETE  = 7,
86         TRACE   = 8,
87         MAX     = 9,
88     }
89 }
90 
91 #[derive(Debug)]
92 #[repr(C)]
93 pub struct HttpResponseData {
94     pub status_code: HttpStatusCode,
95 }
96 
97 #[repr(C)]
98 pub union HttpRequestOrResponse {
99     pub request: *const HttpRequestData,
100     pub response: *const HttpResponseData,
101 }
102 
103 impl Debug for HttpRequestOrResponse {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result104     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
105         // This is a union type, so we can't access the internal data.
106         f.debug_struct("RequestOrResponse").finish()
107     }
108 }
109 
110 #[derive(Clone, Debug)]
111 #[repr(C)]
112 pub struct HttpHeader {
113     pub field_name: *const Char8,
114     pub field_value: *const Char8,
115 }
116 
117 newtype_enum! {
118     pub enum HttpStatusCode: i32 => {
119         STATUS_UNSUPPORTED = 0,
120         STATUS_100_CONTINUE = 1,
121         STATUS_101_SWITCHING_PROTOCOLS = 2,
122         STATUS_200_OK = 3,
123         STATUS_201_CREATED = 4,
124         STATUS_202_ACCEPTED = 5,
125         STATUS_203_NON_AUTHORITATIVE_INFORMATION = 6,
126         STATUS_204_NO_CONTENT = 7,
127         STATUS_205_RESET_CONTENT = 8,
128         STATUS_206_PARTIAL_CONTENT = 9,
129         STATUS_300_MULTIPLE_CHOICES = 10,
130         STATUS_301_MOVED_PERMANENTLY = 11,
131         STATUS_302_FOUND = 12,
132         STATUS_303_SEE_OTHER = 13,
133         STATUS_304_NOT_MODIFIED = 14,
134         STATUS_305_USE_PROXY = 15,
135         STATUS_307_TEMPORARY_REDIRECT = 16,
136         STATUS_400_BAD_REQUEST = 17,
137         STATUS_401_UNAUTHORIZED = 18,
138         STATUS_402_PAYMENT_REQUIRED = 19,
139         STATUS_403_FORBIDDEN = 20,
140         STATUS_404_NOT_FOUND = 21,
141         STATUS_405_METHOD_NOT_ALLOWED = 22,
142         STATUS_406_NOT_ACCEPTABLE = 23,
143         STATUS_407_PROXY_AUTHENTICATION_REQUIRED = 24,
144         STATUS_408_REQUEST_TIME_OUT = 25,
145         STATUS_409_CONFLICT = 26,
146         STATUS_410_GONE = 27,
147         STATUS_411_LENGTH_REQUIRED = 28,
148         STATUS_412_PRECONDITION_FAILED = 29,
149         STATUS_413_REQUEST_ENTITY_TOO_LARGE = 30,
150         STATUS_414_REQUEST_URI_TOO_LARGE = 31,
151         STATUS_415_UNSUPPORTED_MEDIA_TYPE = 32,
152         STATUS_416_REQUESTED_RANGE_NOT_SATISFIED = 33,
153         STATUS_417_EXPECTATION_FAILED = 34,
154         STATUS_500_INTERNAL_SERVER_ERROR = 35,
155         STATUS_501_NOT_IMPLEMENTED = 36,
156         STATUS_502_BAD_GATEWAY = 37,
157         STATUS_503_SERVICE_UNAVAILABLE = 38,
158         STATUS_504_GATEWAY_TIME_OUT = 39,
159         STATUS_505_VERSION_NOT_SUPPORTED = 40,
160         STATUS_308_PERMANENT_REDIRECT = 41,
161     }
162 }
163 
164 #[derive(Debug)]
165 #[repr(C)]
166 pub struct HttpProtocol {
167     pub get_mode_data:
168         unsafe extern "efiapi" fn(this: *const Self, config_data: *mut HttpConfigData) -> Status,
169     pub configure:
170         unsafe extern "efiapi" fn(this: *mut Self, config_data: *const HttpConfigData) -> Status,
171     pub request: unsafe extern "efiapi" fn(this: *mut Self, token: *mut HttpToken) -> Status,
172     pub cancel: unsafe extern "efiapi" fn(this: *mut Self, token: *mut HttpToken) -> Status,
173     pub response: unsafe extern "efiapi" fn(this: *mut Self, token: *mut HttpToken) -> Status,
174     pub poll: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
175 }
176 
177 impl HttpProtocol {
178     pub const GUID: Guid = guid!("7a59b29b-910b-4171-8242-a85a0df25b5b");
179     pub const SERVICE_BINDING_GUID: Guid = guid!("bdc8e6af-d9bc-4379-a72a-e0c4e75dae1c");
180 }
181