]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
DxeTpmMeasureBootLib: Change global variable name to avoid name conflict.
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpProto.c
CommitLineData
47f51a06
YT
1/** @file\r
2 Miscellaneous routines for HttpDxe driver.\r
3\r
4Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
8cfd008e 5(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
47f51a06
YT
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "HttpDriver.h"\r
17\r
18/**\r
19 The common notify function used in HTTP driver. \r
20\r
21 @param[in] Event The event signaled.\r
22 @param[in] Context The context.\r
23\r
24**/\r
25VOID\r
26EFIAPI\r
27HttpCommonNotify (\r
28 IN EFI_EVENT Event,\r
29 IN VOID *Context\r
30 )\r
31{\r
32 if ((Event == NULL) || (Context == NULL)) {\r
33 return ;\r
34 }\r
35\r
36 *((BOOLEAN *) Context) = TRUE;\r
37}\r
38\r
39/**\r
b659408b 40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().\r
47f51a06 41\r
47f51a06
YT
42 @param[in] Context The context.\r
43\r
44**/\r
45VOID\r
46EFIAPI\r
49c9f74c 47HttpTcpTransmitNotifyDpc (\r
47f51a06
YT
48 IN VOID *Context\r
49 )\r
50{\r
51 HTTP_TOKEN_WRAP *Wrap;\r
b659408b 52 HTTP_PROTOCOL *HttpInstance;\r
47f51a06 53\r
49c9f74c 54 if (Context == NULL) {\r
47f51a06
YT
55 return ;\r
56 }\r
b659408b
ZL
57 \r
58 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
59 HttpInstance = Wrap->HttpInstance;\r
60 \r
61 if (!HttpInstance->LocalAddressIsIPv6) {\r
62 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;\r
63 gBS->SignalEvent (Wrap->HttpToken->Event);\r
64\r
65 //\r
66 // Free resources.\r
67 //\r
68 if (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
69 FreePool (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
70 }\r
47f51a06 71\r
b659408b
ZL
72 if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
73 gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
74 }\r
75 \r
76 } else {\r
77 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
78 gBS->SignalEvent (Wrap->HttpToken->Event);\r
79 \r
80 //\r
81 // Free resources.\r
82 //\r
83 if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
84 FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
85 }\r
47f51a06 86\r
b659408b
ZL
87 if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
88 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
89 } \r
47f51a06
YT
90 }\r
91\r
47f51a06
YT
92\r
93 Wrap->TcpWrap.IsTxDone = TRUE;\r
94\r
95 //\r
96 // Check pending TxTokens and sent out.\r
97 //\r
98 NetMapIterate (&Wrap->HttpInstance->TxTokens, HttpTcpTransmit, NULL);\r
99\r
100}\r
101\r
49c9f74c
FS
102/**\r
103 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.\r
104\r
105 @param Event The receive event delivered to TCP for transmit.\r
106 @param Context Context for the callback.\r
107\r
108**/\r
109VOID\r
110EFIAPI\r
111HttpTcpTransmitNotify (\r
112 IN EFI_EVENT Event,\r
113 IN VOID *Context\r
114 )\r
115{\r
116 //\r
117 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
118 //\r
119 QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);\r
120}\r
121\r
47f51a06 122/**\r
b659408b 123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
47f51a06 124\r
47f51a06
YT
125 @param[in] Context The context.\r
126\r
127**/\r
128VOID\r
129EFIAPI\r
49c9f74c 130HttpTcpReceiveNotifyDpc (\r
47f51a06
YT
131 IN VOID *Context\r
132 )\r
133{\r
134 HTTP_TOKEN_WRAP *Wrap;\r
135 NET_MAP_ITEM *Item;\r
136 UINTN Length;\r
137 EFI_STATUS Status;\r
138 HTTP_PROTOCOL *HttpInstance;\r
b659408b 139 BOOLEAN UsingIpv6;\r
47f51a06 140\r
49c9f74c 141 if (Context == NULL) {\r
47f51a06
YT
142 return ;\r
143 }\r
144\r
145 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
47f51a06 146 HttpInstance = Wrap->HttpInstance;\r
b659408b
ZL
147 UsingIpv6 = HttpInstance->LocalAddressIsIPv6;\r
148 \r
149 if (UsingIpv6) {\r
150 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
151 \r
152 if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {\r
153 return ;\r
154 }\r
155\r
156 } else {\r
157 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
158 \r
159 if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
160 return ;\r
161 }\r
162 }\r
47f51a06
YT
163\r
164 //\r
165 // Check whether we receive a complete HTTP message.\r
166 //\r
167 ASSERT (HttpInstance->MsgParser != NULL);\r
b659408b
ZL
168 if (UsingIpv6) {\r
169 Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;\r
170 } else {\r
171 Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;\r
172 }\r
47f51a06 173\r
47f51a06
YT
174 Status = HttpParseMessageBody (\r
175 HttpInstance->MsgParser,\r
176 Length,\r
177 Wrap->HttpToken->Message->Body\r
178 );\r
179 if (EFI_ERROR (Status)) {\r
180 return ;\r
181 }\r
182\r
183 if (HttpIsMessageComplete (HttpInstance->MsgParser)) {\r
184 //\r
185 // Free the MsgParse since we already have a full HTTP message.\r
186 //\r
187 HttpFreeMsgParser (HttpInstance->MsgParser);\r
188 HttpInstance->MsgParser = NULL;\r
189 }\r
190\r
191 Wrap->HttpToken->Message->BodyLength = Length;\r
192 ASSERT (HttpInstance->CacheBody == NULL);\r
193 //\r
194 // We receive part of header of next HTTP msg.\r
195 //\r
196 if (HttpInstance->NextMsg != NULL) {\r
197 Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg - \r
198 (CHAR8 *) Wrap->HttpToken->Message->Body;\r
199 HttpInstance->CacheLen = Length - Wrap->HttpToken->Message->BodyLength;\r
200 if (HttpInstance->CacheLen != 0) {\r
201 HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);\r
202 if (HttpInstance->CacheBody == NULL) {\r
203 return ;\r
204 }\r
205 CopyMem (HttpInstance->CacheBody, HttpInstance->NextMsg, HttpInstance->CacheLen);\r
206 HttpInstance->NextMsg = HttpInstance->CacheBody;\r
207 HttpInstance->CacheOffset = 0;\r
208 }\r
209 }\r
210\r
211 Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);\r
212 if (Item != NULL) {\r
213 NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);\r
214 }\r
215\r
216\r
217 Wrap->TcpWrap.IsRxDone = TRUE;\r
b659408b
ZL
218 if (UsingIpv6) {\r
219 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
220 } else {\r
221 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
222 }\r
223 \r
47f51a06
YT
224\r
225 gBS->SignalEvent (Wrap->HttpToken->Event);\r
226\r
227 //\r
228 // Check pending RxTokens and receive the HTTP message.\r
229 //\r
230 NetMapIterate (&Wrap->HttpInstance->RxTokens, HttpTcpReceive, NULL);\r
231 \r
232 FreePool (Wrap);\r
233}\r
234\r
49c9f74c
FS
235/**\r
236 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.\r
237\r
238 @param Event The receive event delivered to TCP for receive.\r
239 @param Context Context for the callback.\r
240\r
241**/\r
242VOID\r
243EFIAPI\r
244HttpTcpReceiveNotify (\r
245 IN EFI_EVENT Event,\r
246 IN VOID *Context\r
247 )\r
248{\r
249 //\r
250 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
251 //\r
252 QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);\r
253}\r
254\r
47f51a06 255/**\r
b659408b 256 Create events for the TCP connection token and TCP close token.\r
47f51a06
YT
257\r
258 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
259\r
260 @retval EFI_SUCCESS The events are created successfully.\r
261 @retval others Other error as indicated.\r
262\r
263**/\r
264EFI_STATUS\r
b659408b 265HttpCreateTcpConnCloseEvent (\r
47f51a06
YT
266 IN HTTP_PROTOCOL *HttpInstance\r
267 )\r
268{\r
269 EFI_STATUS Status;\r
b659408b
ZL
270\r
271 if (!HttpInstance->LocalAddressIsIPv6) {\r
47f51a06
YT
272 //\r
273 // Create events for variuos asynchronous operations.\r
274 //\r
275 Status = gBS->CreateEvent (\r
276 EVT_NOTIFY_SIGNAL,\r
277 TPL_NOTIFY,\r
278 HttpCommonNotify,\r
b659408b
ZL
279 &HttpInstance->IsTcp4ConnDone,\r
280 &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
47f51a06
YT
281 );\r
282 if (EFI_ERROR (Status)) {\r
283 goto ERROR;\r
284 }\r
285\r
286 //\r
b659408b
ZL
287 // Initialize Tcp4CloseToken\r
288 //\r
289 Status = gBS->CreateEvent (\r
290 EVT_NOTIFY_SIGNAL,\r
291 TPL_NOTIFY,\r
292 HttpCommonNotify,\r
293 &HttpInstance->IsTcp4CloseDone,\r
294 &HttpInstance->Tcp4CloseToken.CompletionToken.Event\r
295 );\r
296 if (EFI_ERROR (Status)) {\r
297 goto ERROR;\r
298 }\r
299 \r
300 } else {\r
301 //\r
302 // Create events for variuos asynchronous operations.\r
47f51a06
YT
303 //\r
304 Status = gBS->CreateEvent (\r
305 EVT_NOTIFY_SIGNAL,\r
306 TPL_NOTIFY,\r
307 HttpCommonNotify,\r
b659408b
ZL
308 &HttpInstance->IsTcp6ConnDone,\r
309 &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
47f51a06
YT
310 );\r
311 if (EFI_ERROR (Status)) {\r
312 goto ERROR;\r
313 }\r
314\r
b659408b
ZL
315 //\r
316 // Initialize Tcp6CloseToken\r
317 //\r
318 Status = gBS->CreateEvent (\r
319 EVT_NOTIFY_SIGNAL,\r
320 TPL_NOTIFY,\r
321 HttpCommonNotify,\r
322 &HttpInstance->IsTcp6CloseDone,\r
323 &HttpInstance->Tcp6CloseToken.CompletionToken.Event\r
324 );\r
325 if (EFI_ERROR (Status)) {\r
326 goto ERROR;\r
327 }\r
328 }\r
329 \r
47f51a06
YT
330 return EFI_SUCCESS;\r
331\r
332ERROR:\r
333 //\r
334 // Error handling\r
335 //\r
b659408b 336 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
337\r
338 return Status;\r
339}\r
340\r
341\r
342/**\r
b659408b 343 Close events in the TCP connection token and TCP close token.\r
47f51a06
YT
344\r
345 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
346\r
347**/\r
348VOID\r
b659408b 349HttpCloseTcpConnCloseEvent (\r
47f51a06
YT
350 IN HTTP_PROTOCOL *HttpInstance\r
351 )\r
352{\r
353 ASSERT (HttpInstance != NULL);\r
354\r
b659408b
ZL
355 if (HttpInstance->LocalAddressIsIPv6) {\r
356 if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {\r
357 gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);\r
358 HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;\r
359 }\r
47f51a06 360\r
b659408b
ZL
361 if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {\r
362 gBS->CloseEvent(HttpInstance->Tcp6CloseToken.CompletionToken.Event);\r
363 HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;\r
364 }\r
365\r
366 } else {\r
367 if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {\r
368 gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);\r
369 HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;\r
370 }\r
371\r
372 if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {\r
373 gBS->CloseEvent(HttpInstance->Tcp4CloseToken.CompletionToken.Event);\r
374 HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;\r
375 }\r
376 }\r
377 \r
47f51a06
YT
378}\r
379\r
380/**\r
b659408b 381 Create event for the TCP transmit token.\r
47f51a06
YT
382\r
383 @param[in] Wrap Point to HTTP token's wrap data.\r
384\r
385 @retval EFI_SUCCESS The events is created successfully.\r
386 @retval others Other error as indicated.\r
387\r
388**/\r
389EFI_STATUS\r
b659408b 390HttpCreateTcpTxEvent (\r
47f51a06
YT
391 IN HTTP_TOKEN_WRAP *Wrap\r
392 )\r
393{\r
394 EFI_STATUS Status;\r
b659408b 395 HTTP_PROTOCOL *HttpInstance;\r
47f51a06
YT
396 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
397\r
b659408b 398 HttpInstance = Wrap->HttpInstance;\r
47f51a06
YT
399 TcpWrap = &Wrap->TcpWrap;\r
400\r
b659408b
ZL
401 if (!HttpInstance->LocalAddressIsIPv6) {\r
402 Status = gBS->CreateEvent (\r
403 EVT_NOTIFY_SIGNAL,\r
404 TPL_NOTIFY,\r
405 HttpTcpTransmitNotify,\r
406 Wrap,\r
407 &TcpWrap->Tx4Token.CompletionToken.Event\r
408 );\r
409 if (EFI_ERROR (Status)) {\r
410 return Status;\r
411 }\r
412 \r
413 TcpWrap->Tx4Data.Push = TRUE;\r
414 TcpWrap->Tx4Data.Urgent = FALSE;\r
415 TcpWrap->Tx4Data.FragmentCount = 1;\r
416 TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;\r
417 TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 418\r
b659408b
ZL
419 } else {\r
420 Status = gBS->CreateEvent (\r
421 EVT_NOTIFY_SIGNAL,\r
422 TPL_NOTIFY,\r
423 HttpTcpTransmitNotify,\r
424 Wrap,\r
425 &TcpWrap->Tx6Token.CompletionToken.Event\r
426 );\r
427 if (EFI_ERROR (Status)) {\r
428 return Status;\r
429 }\r
47f51a06 430\r
b659408b
ZL
431 TcpWrap->Tx6Data.Push = TRUE;\r
432 TcpWrap->Tx6Data.Urgent = FALSE;\r
433 TcpWrap->Tx6Data.FragmentCount = 1;\r
434 TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;\r
435 TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY;\r
436 \r
437 \r
438 }\r
439 \r
47f51a06
YT
440 return EFI_SUCCESS;\r
441}\r
442\r
443/**\r
b659408b 444 Create event for the TCP receive token which is used to receive HTTP header.\r
47f51a06
YT
445\r
446 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
447\r
448 @retval EFI_SUCCESS The events is created successfully.\r
449 @retval others Other error as indicated.\r
450\r
451**/\r
452EFI_STATUS\r
b659408b 453HttpCreateTcpRxEventForHeader (\r
47f51a06
YT
454 IN HTTP_PROTOCOL *HttpInstance\r
455 )\r
456{\r
457 EFI_STATUS Status;\r
458\r
b659408b
ZL
459 if (!HttpInstance->LocalAddressIsIPv6) {\r
460 Status = gBS->CreateEvent (\r
461 EVT_NOTIFY_SIGNAL,\r
462 TPL_NOTIFY,\r
463 HttpCommonNotify,\r
464 &HttpInstance->IsRxDone,\r
465 &HttpInstance->Rx4Token.CompletionToken.Event\r
466 );\r
467 if (EFI_ERROR (Status)) {\r
468 return Status;\r
469 }\r
470 \r
471 HttpInstance->Rx4Data.FragmentCount = 1;\r
472 HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;\r
473 HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 474\r
b659408b
ZL
475 } else {\r
476 Status = gBS->CreateEvent (\r
477 EVT_NOTIFY_SIGNAL,\r
478 TPL_NOTIFY,\r
479 HttpCommonNotify,\r
480 &HttpInstance->IsRxDone,\r
481 &HttpInstance->Rx6Token.CompletionToken.Event\r
482 );\r
483 if (EFI_ERROR (Status)) {\r
484 return Status;\r
485 }\r
486\r
487 HttpInstance->Rx6Data.FragmentCount =1;\r
488 HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;\r
489 HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
490 \r
47f51a06
YT
491 }\r
492\r
47f51a06
YT
493\r
494 return EFI_SUCCESS;\r
495}\r
496\r
497/**\r
b659408b 498 Create event for the TCP receive token which is used to receive HTTP body.\r
47f51a06
YT
499\r
500 @param[in] Wrap Point to HTTP token's wrap data.\r
501\r
502 @retval EFI_SUCCESS The events is created successfully.\r
503 @retval others Other error as indicated.\r
504\r
505**/\r
506EFI_STATUS\r
b659408b 507HttpCreateTcpRxEvent (\r
47f51a06
YT
508 IN HTTP_TOKEN_WRAP *Wrap \r
509 )\r
510{\r
511 EFI_STATUS Status;\r
b659408b 512 HTTP_PROTOCOL *HttpInstance;\r
47f51a06
YT
513 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
514\r
b659408b 515 HttpInstance = Wrap->HttpInstance;\r
47f51a06 516 TcpWrap = &Wrap->TcpWrap;\r
b659408b
ZL
517 if (!HttpInstance->LocalAddressIsIPv6) {\r
518 Status = gBS->CreateEvent (\r
519 EVT_NOTIFY_SIGNAL,\r
520 TPL_NOTIFY,\r
521 HttpTcpReceiveNotify,\r
522 Wrap,\r
523 &TcpWrap->Rx4Token.CompletionToken.Event\r
524 );\r
525 if (EFI_ERROR (Status)) {\r
526 return Status;\r
527 }\r
528 \r
529 TcpWrap->Rx4Data.FragmentCount = 1;\r
530 TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;\r
531 TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 532\r
b659408b
ZL
533 } else {\r
534 Status = gBS->CreateEvent (\r
535 EVT_NOTIFY_SIGNAL,\r
536 TPL_NOTIFY,\r
537 HttpTcpReceiveNotify,\r
538 Wrap,\r
539 &TcpWrap->Rx6Token.CompletionToken.Event\r
540 ); \r
541 if (EFI_ERROR (Status)) {\r
542 return Status;\r
543 }\r
544\r
545 TcpWrap->Rx6Data.FragmentCount = 1;\r
546 TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;\r
547 TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 548 }\r
b659408b
ZL
549 \r
550 return EFI_SUCCESS;\r
551}\r
47f51a06 552\r
b659408b
ZL
553/**\r
554 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
47f51a06 555\r
b659408b
ZL
556 @param[in] Wrap Pointer to HTTP token's wrap data.\r
557 \r
558**/\r
559VOID\r
560HttpCloseTcpRxEvent (\r
561 IN HTTP_TOKEN_WRAP *Wrap\r
562 )\r
563{\r
564 HTTP_PROTOCOL *HttpInstance;\r
565 EFI_TCP4_IO_TOKEN *Rx4Token;\r
566 EFI_TCP6_IO_TOKEN *Rx6Token;\r
567\r
1b96428d 568 ASSERT (Wrap != NULL);\r
b659408b
ZL
569 HttpInstance = Wrap->HttpInstance;\r
570 Rx4Token = NULL;\r
571 Rx6Token = NULL;\r
572 \r
573 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d
ZL
574 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
575 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
b659408b
ZL
576 }\r
577\r
578 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
579 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
580 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
581 }\r
582 } else {\r
1b96428d
ZL
583 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
584 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
b659408b
ZL
585 }\r
586 \r
587 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
588 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
589 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
590 }\r
591 }\r
47f51a06
YT
592}\r
593\r
594/**\r
595 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.\r
596\r
47f51a06 597 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
b659408b 598 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
47f51a06
YT
599\r
600 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully. \r
601 @retval Others Other error as indicated.\r
602\r
603**/\r
604EFI_STATUS\r
605HttpInitProtocol (\r
b659408b
ZL
606 IN OUT HTTP_PROTOCOL *HttpInstance,\r
607 IN BOOLEAN IpVersion\r
47f51a06
YT
608 )\r
609{\r
610 EFI_STATUS Status;\r
611 VOID *Interface;\r
b659408b
ZL
612 BOOLEAN UsingIpv6;\r
613 \r
614 ASSERT (HttpInstance != NULL);\r
615 UsingIpv6 = IpVersion;\r
616 \r
617 if (!UsingIpv6) {\r
618 //\r
619 // Create TCP4 child.\r
620 //\r
621 Status = NetLibCreateServiceChild (\r
622 HttpInstance->Service->ControllerHandle,\r
623 HttpInstance->Service->ImageHandle,\r
624 &gEfiTcp4ServiceBindingProtocolGuid,\r
625 &HttpInstance->Tcp4ChildHandle\r
626 );\r
47f51a06 627\r
b659408b
ZL
628 if (EFI_ERROR (Status)) {\r
629 goto ON_ERROR;\r
630 }\r
47f51a06 631\r
b659408b
ZL
632 Status = gBS->OpenProtocol (\r
633 HttpInstance->Tcp4ChildHandle,\r
634 &gEfiTcp4ProtocolGuid,\r
635 (VOID **) &Interface,\r
636 HttpInstance->Service->ImageHandle,\r
637 HttpInstance->Service->ControllerHandle,\r
638 EFI_OPEN_PROTOCOL_BY_DRIVER\r
639 );\r
640 \r
641 if (EFI_ERROR (Status)) {\r
642 goto ON_ERROR;\r
643 }\r
47f51a06 644\r
b659408b
ZL
645 Status = gBS->OpenProtocol (\r
646 HttpInstance->Tcp4ChildHandle,\r
647 &gEfiTcp4ProtocolGuid,\r
648 (VOID **) &HttpInstance->Tcp4,\r
649 HttpInstance->Service->ImageHandle,\r
650 HttpInstance->Handle,\r
651 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
652 );\r
653 if (EFI_ERROR(Status)) {\r
654 goto ON_ERROR;\r
655 }\r
47f51a06 656\r
b659408b
ZL
657 Status = gBS->OpenProtocol (\r
658 HttpInstance->Service->Tcp4ChildHandle,\r
659 &gEfiTcp4ProtocolGuid,\r
660 (VOID **) &Interface,\r
661 HttpInstance->Service->ImageHandle,\r
662 HttpInstance->Handle,\r
663 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
664 );\r
665 if (EFI_ERROR(Status)) {\r
666 goto ON_ERROR;\r
667 }\r
668 } else {\r
669 //\r
670 // Create TCP6 Child.\r
671 //\r
672 Status = NetLibCreateServiceChild (\r
673 HttpInstance->Service->ControllerHandle,\r
674 HttpInstance->Service->ImageHandle,\r
675 &gEfiTcp6ServiceBindingProtocolGuid,\r
676 &HttpInstance->Tcp6ChildHandle\r
677 );\r
47f51a06 678\r
b659408b
ZL
679 if (EFI_ERROR (Status)) {\r
680 goto ON_ERROR;\r
681 }\r
47f51a06 682\r
b659408b
ZL
683 Status = gBS->OpenProtocol (\r
684 HttpInstance->Tcp6ChildHandle,\r
685 &gEfiTcp6ProtocolGuid,\r
686 (VOID **) &Interface,\r
687 HttpInstance->Service->ImageHandle,\r
688 HttpInstance->Service->ControllerHandle,\r
689 EFI_OPEN_PROTOCOL_BY_DRIVER\r
690 );\r
691 \r
692 if (EFI_ERROR (Status)) {\r
693 goto ON_ERROR;\r
694 }\r
695\r
696 Status = gBS->OpenProtocol (\r
697 HttpInstance->Tcp6ChildHandle,\r
698 &gEfiTcp6ProtocolGuid,\r
699 (VOID **) &HttpInstance->Tcp6,\r
700 HttpInstance->Service->ImageHandle,\r
701 HttpInstance->Handle,\r
702 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
703 );\r
704 \r
705 if (EFI_ERROR(Status)) {\r
706 goto ON_ERROR;\r
707 } \r
708\r
709 Status = gBS->OpenProtocol (\r
710 HttpInstance->Service->Tcp6ChildHandle,\r
711 &gEfiTcp6ProtocolGuid,\r
712 (VOID **) &Interface,\r
713 HttpInstance->Service->ImageHandle,\r
714 HttpInstance->Handle,\r
715 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
716 );\r
47f51a06 717\r
b659408b
ZL
718 if (EFI_ERROR(Status)) {\r
719 goto ON_ERROR;\r
720 }\r
721 }\r
722 \r
51b0450e
FS
723 HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);\r
724 if (HttpInstance->Url == NULL) {\r
725 Status = EFI_OUT_OF_RESOURCES;\r
726 goto ON_ERROR;\r
727 }\r
728\r
47f51a06
YT
729 return EFI_SUCCESS;\r
730\r
731ON_ERROR:\r
732 \r
b659408b 733 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 734 gBS->CloseProtocol (\r
b659408b 735 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
736 &gEfiTcp4ProtocolGuid,\r
737 HttpInstance->Service->ImageHandle,\r
738 HttpInstance->Service->ControllerHandle\r
739 );\r
740\r
741 gBS->CloseProtocol (\r
b659408b 742 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
743 &gEfiTcp4ProtocolGuid,\r
744 HttpInstance->Service->ImageHandle,\r
745 HttpInstance->Handle\r
b659408b 746 ); \r
47f51a06
YT
747 \r
748 NetLibDestroyServiceChild (\r
749 HttpInstance->Service->ControllerHandle,\r
750 HttpInstance->Service->ImageHandle,\r
751 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 752 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
753 );\r
754 }\r
b659408b
ZL
755 \r
756 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
757 gBS->CloseProtocol (\r
758 HttpInstance->Service->Tcp4ChildHandle,\r
759 &gEfiTcp4ProtocolGuid,\r
760 HttpInstance->Service->ImageHandle,\r
761 HttpInstance->Handle\r
762 );\r
763 }\r
764 \r
765 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
766 gBS->CloseProtocol (\r
767 HttpInstance->Tcp6ChildHandle,\r
768 &gEfiTcp6ProtocolGuid,\r
769 HttpInstance->Service->ImageHandle,\r
770 HttpInstance->Service->ControllerHandle\r
771 );\r
47f51a06 772\r
b659408b
ZL
773 gBS->CloseProtocol (\r
774 HttpInstance->Tcp6ChildHandle,\r
775 &gEfiTcp6ProtocolGuid,\r
776 HttpInstance->Service->ImageHandle,\r
777 HttpInstance->Handle\r
778 );\r
779 \r
780 NetLibDestroyServiceChild (\r
781 HttpInstance->Service->ControllerHandle,\r
782 HttpInstance->Service->ImageHandle,\r
783 &gEfiTcp6ServiceBindingProtocolGuid,\r
784 HttpInstance->Tcp6ChildHandle\r
785 );\r
786 }\r
787 \r
788 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
789 gBS->CloseProtocol (\r
790 HttpInstance->Service->Tcp6ChildHandle,\r
791 &gEfiTcp6ProtocolGuid,\r
792 HttpInstance->Service->ImageHandle,\r
793 HttpInstance->Handle\r
794 );\r
795 }\r
796\r
797 return EFI_UNSUPPORTED;\r
47f51a06
YT
798 \r
799}\r
800\r
801/**\r
802 Clean up the HTTP child, release all the resources used by it.\r
803\r
804 @param[in] HttpInstance The HTTP child to clean up.\r
805\r
806**/\r
807VOID\r
808HttpCleanProtocol (\r
809 IN HTTP_PROTOCOL *HttpInstance\r
810 )\r
811{\r
812 HttpCloseConnection (HttpInstance);\r
813 \r
b659408b 814 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
815\r
816 if (HttpInstance->CacheBody != NULL) {\r
817 FreePool (HttpInstance->CacheBody);\r
818 HttpInstance->CacheBody = NULL;\r
819 HttpInstance->NextMsg = NULL;\r
820 }\r
821\r
822 if (HttpInstance->RemoteHost != NULL) {\r
823 FreePool (HttpInstance->RemoteHost);\r
824 HttpInstance->RemoteHost = NULL;\r
825 }\r
826\r
827 if (HttpInstance->MsgParser != NULL) {\r
828 HttpFreeMsgParser (HttpInstance->MsgParser);\r
829 HttpInstance->MsgParser = NULL;\r
830 }\r
b659408b 831 \r
51b0450e
FS
832 if (HttpInstance->Url != NULL) {\r
833 FreePool (HttpInstance->Url);\r
834 HttpInstance->Url = NULL;\r
835 }\r
b659408b 836 \r
47f51a06
YT
837 NetMapClean (&HttpInstance->TxTokens);\r
838 NetMapClean (&HttpInstance->RxTokens);\r
839\r
b659408b 840 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 841 gBS->CloseProtocol (\r
b659408b 842 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
843 &gEfiTcp4ProtocolGuid,\r
844 HttpInstance->Service->ImageHandle,\r
845 HttpInstance->Service->ControllerHandle\r
846 );\r
847\r
848 gBS->CloseProtocol (\r
b659408b 849 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
850 &gEfiTcp4ProtocolGuid,\r
851 HttpInstance->Service->ImageHandle,\r
852 HttpInstance->Handle\r
853 );\r
854 \r
855 NetLibDestroyServiceChild (\r
856 HttpInstance->Service->ControllerHandle,\r
857 HttpInstance->Service->ImageHandle,\r
858 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 859 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
860 );\r
861 }\r
b659408b
ZL
862\r
863 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
864 gBS->CloseProtocol (\r
865 HttpInstance->Service->Tcp4ChildHandle,\r
866 &gEfiTcp4ProtocolGuid,\r
867 HttpInstance->Service->ImageHandle,\r
868 HttpInstance->Handle\r
869 );\r
870 } \r
871\r
872 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
873 gBS->CloseProtocol (\r
874 HttpInstance->Tcp6ChildHandle,\r
875 &gEfiTcp6ProtocolGuid,\r
876 HttpInstance->Service->ImageHandle,\r
877 HttpInstance->Service->ControllerHandle\r
878 );\r
879\r
880 gBS->CloseProtocol (\r
881 HttpInstance->Tcp6ChildHandle,\r
882 &gEfiTcp6ProtocolGuid,\r
883 HttpInstance->Service->ImageHandle,\r
884 HttpInstance->Handle\r
885 );\r
886 \r
887 NetLibDestroyServiceChild (\r
888 HttpInstance->Service->ControllerHandle,\r
889 HttpInstance->Service->ImageHandle,\r
890 &gEfiTcp6ServiceBindingProtocolGuid,\r
891 HttpInstance->Tcp6ChildHandle\r
892 );\r
893 }\r
894 \r
895 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
896 gBS->CloseProtocol (\r
897 HttpInstance->Service->Tcp6ChildHandle,\r
898 &gEfiTcp6ProtocolGuid,\r
899 HttpInstance->Service->ImageHandle,\r
900 HttpInstance->Handle\r
901 );\r
902 }\r
903 \r
47f51a06
YT
904}\r
905\r
906/**\r
907 Establish TCP connection with HTTP server.\r
908\r
909 @param[in] HttpInstance The HTTP instance private data.\r
910\r
911 @retval EFI_SUCCESS The TCP connection is established.\r
912 @retval Others Other error as indicated.\r
913\r
914**/\r
915EFI_STATUS\r
916HttpCreateConnection (\r
917 IN HTTP_PROTOCOL *HttpInstance\r
918 )\r
919{\r
920 EFI_STATUS Status;\r
921\r
47f51a06
YT
922 //\r
923 // Connect to Http server\r
924 //\r
b659408b
ZL
925 if (!HttpInstance->LocalAddressIsIPv6) {\r
926 HttpInstance->IsTcp4ConnDone = FALSE;\r
927 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
928 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
929 if (EFI_ERROR (Status)) {\r
930 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
931 return Status;\r
932 }\r
933 \r
934 while (!HttpInstance->IsTcp4ConnDone) {\r
935 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
936 }\r
937 \r
938 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
939 \r
940 } else {\r
941 HttpInstance->IsTcp6ConnDone = FALSE;\r
942 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
943 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
944 if (EFI_ERROR (Status)) {\r
945 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
946 return Status;\r
947 }\r
47f51a06 948\r
b659408b
ZL
949 while(!HttpInstance->IsTcp6ConnDone) {\r
950 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
951 }\r
47f51a06 952\r
b659408b
ZL
953 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status; \r
954 }\r
955 \r
47f51a06
YT
956 if (!EFI_ERROR (Status)) {\r
957 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
958 }\r
959\r
960 return Status;\r
961}\r
962\r
963/**\r
964 Close existing TCP connection.\r
965\r
966 @param[in] HttpInstance The HTTP instance private data.\r
967\r
968 @retval EFI_SUCCESS The TCP connection is closed.\r
969 @retval Others Other error as indicated.\r
970\r
971**/\r
972EFI_STATUS\r
973HttpCloseConnection (\r
974 IN HTTP_PROTOCOL *HttpInstance\r
975 )\r
976{\r
977 EFI_STATUS Status;\r
978\r
374ecd04 979 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
47f51a06 980\r
b659408b
ZL
981 if (HttpInstance->LocalAddressIsIPv6) {\r
982 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
983 HttpInstance->IsTcp6CloseDone = FALSE;\r
984 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
985 if (EFI_ERROR (Status)) {\r
986 return Status;\r
987 }\r
988\r
989 while (!HttpInstance->IsTcp6CloseDone) {\r
990 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
991 }\r
992 \r
993 } else {\r
994 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
995 HttpInstance->IsTcp4CloseDone = FALSE;\r
996 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
997 if (EFI_ERROR (Status)) {\r
998 return Status;\r
999 }\r
1000\r
1001 while (!HttpInstance->IsTcp4CloseDone) {\r
1002 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
1003 }\r
374ecd04 1004 }\r
b659408b 1005\r
47f51a06
YT
1006 }\r
1007\r
1008 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
374ecd04 1009 return EFI_SUCCESS;\r
47f51a06
YT
1010}\r
1011\r
1012/**\r
1013 Configure TCP4 protocol child.\r
1014\r
1015 @param[in] HttpInstance The HTTP instance private data.\r
1016 @param[in] Wrap The HTTP token's wrap data.\r
1017\r
1018 @retval EFI_SUCCESS The TCP4 protocol child is configured.\r
1019 @retval Others Other error as indicated.\r
1020\r
1021**/\r
1022EFI_STATUS\r
1023HttpConfigureTcp4 (\r
1024 IN HTTP_PROTOCOL *HttpInstance,\r
1025 IN HTTP_TOKEN_WRAP *Wrap\r
1026 )\r
1027{\r
1028 EFI_STATUS Status;\r
1029 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;\r
1030 EFI_TCP4_ACCESS_POINT *Tcp4AP;\r
1031 EFI_TCP4_OPTION *Tcp4Option;\r
47f51a06
YT
1032\r
1033 ASSERT (HttpInstance != NULL);\r
47f51a06
YT
1034\r
1035\r
1036 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1037 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
1038 \r
1039 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
1040 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;\r
1041 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
1042\r
1043 Tcp4AP = &Tcp4CfgData->AccessPoint;\r
1044 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;\r
1045 if (!Tcp4AP->UseDefaultAddress) {\r
1046 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
1047 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
1048 }\r
1049 \r
1050 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
1051 Tcp4AP->RemotePort = HttpInstance->RemotePort;\r
1052 Tcp4AP->ActiveFlag = TRUE;\r
1053 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);\r
1054\r
1055 Tcp4Option = Tcp4CfgData->ControlOption;\r
1056 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1057 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1058 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1059 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1060 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;\r
1061 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1062 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1063 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1064 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1065 Tcp4Option->EnableNagle = TRUE;\r
1066 Tcp4CfgData->ControlOption = Tcp4Option;\r
1067\r
1068 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);\r
1069 if (EFI_ERROR (Status)) {\r
1070 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status));\r
1071 return Status;\r
1072 }\r
1073\r
b659408b
ZL
1074 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1075 if (EFI_ERROR (Status)) {\r
1076 return Status;\r
1077 }\r
1078\r
1079 Status = HttpCreateTcpTxEvent (Wrap);\r
1080 if (EFI_ERROR (Status)) {\r
1081 return Status;\r
1082 }\r
1083\r
1084 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1085\r
1086 return EFI_SUCCESS;\r
1087}\r
1088\r
1089/**\r
1090 Configure TCP6 protocol child.\r
1091\r
1092 @param[in] HttpInstance The HTTP instance private data.\r
1093 @param[in] Wrap The HTTP token's wrap data.\r
1094\r
1095 @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
1096 @retval Others Other error as indicated.\r
1097\r
1098**/\r
1099EFI_STATUS\r
1100HttpConfigureTcp6 (\r
1101 IN HTTP_PROTOCOL *HttpInstance,\r
1102 IN HTTP_TOKEN_WRAP *Wrap\r
1103 )\r
1104{\r
1105 EFI_STATUS Status;\r
1106 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
1107 EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
1108 EFI_TCP6_OPTION *Tcp6Option;\r
1109 \r
1110 ASSERT (HttpInstance != NULL);\r
1111 \r
1112 Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
1113 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
1114\r
1115 Tcp6CfgData->TrafficClass = 0;\r
1116 Tcp6CfgData->HopLimit = 255;\r
1117 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
1118 \r
1119 Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
1120 Tcp6Ap->ActiveFlag = TRUE;\r
1121 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
1122 Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
1123 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
1124 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
1125\r
1126 Tcp6Option = Tcp6CfgData->ControlOption;\r
1127 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1128 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1129 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1130 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1131 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
1132 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1133 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1134 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1135 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1136 Tcp6Option->EnableNagle = TRUE;\r
1137\r
1138 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1139 if (EFI_ERROR (Status)) {\r
1140 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
1141 return Status;\r
1142 }\r
1143 \r
1144 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
1145 if (EFI_ERROR (Status)) {\r
1146 return Status;\r
1147 }\r
1148\r
b659408b 1149 Status = HttpCreateTcpTxEvent (Wrap);\r
47f51a06
YT
1150 if (EFI_ERROR (Status)) {\r
1151 return Status;\r
1152 }\r
1153\r
1154 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1155\r
1156 return EFI_SUCCESS;\r
b659408b 1157 \r
47f51a06
YT
1158}\r
1159\r
1160/**\r
b659408b 1161 Check existing TCP connection, if in error state, recover TCP4 connection.\r
47f51a06
YT
1162\r
1163 @param[in] HttpInstance The HTTP instance private data.\r
1164\r
1165 @retval EFI_SUCCESS The TCP connection is established.\r
1166 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1167 @retval Others Other error as indicated.\r
1168\r
1169**/\r
1170EFI_STATUS\r
1171HttpConnectTcp4 (\r
1172 IN HTTP_PROTOCOL *HttpInstance\r
1173 )\r
1174{\r
1175 EFI_STATUS Status;\r
1176 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
1177\r
1178\r
a2e61982 1179 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
47f51a06
YT
1180 return EFI_NOT_READY;\r
1181 }\r
1182\r
1183 Status = HttpInstance->Tcp4->GetModeData(\r
1184 HttpInstance->Tcp4, \r
1185 &Tcp4State, \r
1186 NULL,\r
1187 NULL,\r
1188 NULL,\r
1189 NULL\r
1190 );\r
1191 if (EFI_ERROR(Status)){\r
1192 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
1193 return Status;\r
1194 }\r
1195\r
a2e61982
ZL
1196 if (Tcp4State == Tcp4StateEstablished) {\r
1197 return EFI_SUCCESS;\r
1198 } else if (Tcp4State > Tcp4StateEstablished ) {\r
47f51a06 1199 HttpCloseConnection(HttpInstance);\r
a2e61982 1200 }\r
47f51a06
YT
1201\r
1202 return HttpCreateConnection (HttpInstance);\r
1203}\r
1204\r
1205/**\r
b659408b
ZL
1206 Check existing TCP connection, if in error state, recover TCP6 connection.\r
1207\r
1208 @param[in] HttpInstance The HTTP instance private data.\r
1209\r
1210 @retval EFI_SUCCESS The TCP connection is established.\r
1211 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1212 @retval Others Other error as indicated.\r
1213\r
1214**/\r
1215EFI_STATUS\r
1216HttpConnectTcp6 (\r
1217 IN HTTP_PROTOCOL *HttpInstance\r
1218 )\r
1219{\r
1220 EFI_STATUS Status;\r
1221 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
1222\r
a2e61982 1223 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
b659408b
ZL
1224 return EFI_NOT_READY;\r
1225 }\r
1226\r
1227 Status = HttpInstance->Tcp6->GetModeData (\r
1228 HttpInstance->Tcp6,\r
1229 &Tcp6State,\r
1230 NULL,\r
1231 NULL,\r
1232 NULL,\r
1233 NULL\r
1234 );\r
1235 \r
1236 if (EFI_ERROR(Status)){\r
1237 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1238 return Status;\r
1239 }\r
1240\r
a2e61982
ZL
1241 if (Tcp6State == Tcp6StateEstablished) {\r
1242 return EFI_SUCCESS;\r
1243 } else if (Tcp6State > Tcp6StateEstablished ) {\r
1244 HttpCloseConnection(HttpInstance);\r
b659408b
ZL
1245 }\r
1246\r
1247 return HttpCreateConnection (HttpInstance);\r
1248}\r
1249\r
1250/**\r
1251 Initialize TCP related data.\r
1252\r
1253 @param[in] HttpInstance The HTTP instance private data.\r
1254 @param[in] Wrap The HTTP token's wrap data.\r
a2e61982 1255 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.\r
b659408b
ZL
1256\r
1257 @retval EFI_SUCCESS The initialization of TCP instance is done. \r
1258 @retval Others Other error as indicated.\r
1259\r
1260**/\r
1261EFI_STATUS\r
1262HttpInitTcp (\r
1263 IN HTTP_PROTOCOL *HttpInstance,\r
a2e61982
ZL
1264 IN HTTP_TOKEN_WRAP *Wrap,\r
1265 IN BOOLEAN Configure\r
b659408b
ZL
1266 )\r
1267{\r
1268 EFI_STATUS Status;\r
1269 ASSERT (HttpInstance != NULL);\r
1270\r
1271 if (!HttpInstance->LocalAddressIsIPv6) {\r
1272 //\r
1273 // Configure TCP instance.\r
1274 //\r
a2e61982
ZL
1275 if (Configure) {\r
1276 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1277 if (EFI_ERROR (Status)) {\r
1278 return Status;\r
1279 }\r
b659408b 1280 }\r
a2e61982 1281\r
b659408b
ZL
1282 //\r
1283 // Connect TCP.\r
1284 //\r
1285 Status = HttpConnectTcp4 (HttpInstance);\r
1286 if (EFI_ERROR (Status)) {\r
1287 return Status;\r
1288 }\r
1289 } else {\r
1290 //\r
1291 // Configure TCP instance.\r
1292 //\r
a2e61982
ZL
1293 if (Configure) {\r
1294 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1295 if (EFI_ERROR (Status)) {\r
1296 return Status;\r
1297 }\r
b659408b 1298 }\r
a2e61982 1299\r
b659408b
ZL
1300 //\r
1301 // Connect TCP.\r
1302 //\r
1303 Status = HttpConnectTcp6 (HttpInstance);\r
1304 if (EFI_ERROR (Status)) {\r
1305 return Status;\r
1306 }\r
1307 }\r
1308 \r
1309 return EFI_SUCCESS;\r
1310 \r
1311}\r
1312\r
1313/**\r
1314 Send the HTTP message through TCP4 or TCP6.\r
47f51a06
YT
1315\r
1316 @param[in] HttpInstance The HTTP instance private data.\r
1317 @param[in] Wrap The HTTP token's wrap data.\r
1318 @param[in] TxString Buffer containing the HTTP message string.\r
1319 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1320\r
1321 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1322 @retval Others Other error as indicated.\r
1323\r
1324**/\r
1325EFI_STATUS\r
b659408b 1326HttpTransmitTcp (\r
47f51a06
YT
1327 IN HTTP_PROTOCOL *HttpInstance,\r
1328 IN HTTP_TOKEN_WRAP *Wrap,\r
1329 IN UINT8 *TxString,\r
1330 IN UINTN TxStringLen\r
1331 )\r
1332{\r
1333 EFI_STATUS Status;\r
b659408b 1334 EFI_TCP4_IO_TOKEN *Tx4Token;\r
47f51a06 1335 EFI_TCP4_PROTOCOL *Tcp4;\r
b659408b
ZL
1336 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1337 EFI_TCP6_PROTOCOL *Tcp6;\r
47f51a06 1338 \r
b659408b
ZL
1339 if (!HttpInstance->LocalAddressIsIPv6) { \r
1340 Tcp4 = HttpInstance->Tcp4;\r
1341 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
1342 \r
1343 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1344 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1345 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1346 Tx4Token->CompletionToken.Status = EFI_NOT_READY; \r
1347 \r
1348 Wrap->TcpWrap.IsTxDone = FALSE;\r
1349 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1350 if (EFI_ERROR (Status)) {\r
1351 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1352 return Status;\r
1353 }\r
47f51a06 1354\r
b659408b
ZL
1355 } else {\r
1356 Tcp6 = HttpInstance->Tcp6;\r
1357 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
47f51a06 1358\r
b659408b
ZL
1359 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1360 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1361 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1362 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1363\r
1364 Wrap->TcpWrap.IsTxDone = FALSE;\r
1365 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1366 if (EFI_ERROR (Status)) {\r
1367 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1368 return Status;\r
1369 }\r
47f51a06 1370 }\r
b659408b 1371 \r
47f51a06
YT
1372\r
1373 return Status;\r
1374}\r
1375\r
1376/**\r
1377 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined \r
1378 in UEFI 2.5 specification.\r
1379\r
1380 @param[in] StatusCode The status code value in HTTP message.\r
1381\r
1382 @return Value defined in EFI_HTTP_STATUS_CODE .\r
1383\r
1384**/\r
1385EFI_HTTP_STATUS_CODE\r
1386HttpMappingToStatusCode (\r
1387 IN UINTN StatusCode\r
1388 ) \r
1389{\r
1390 switch (StatusCode) {\r
1391 case 100:\r
1392 return HTTP_STATUS_100_CONTINUE;\r
1393 case 101:\r
1394 return HTTP_STATUS_101_SWITCHING_PROTOCOLS;\r
1395 case 200:\r
1396 return HTTP_STATUS_200_OK;\r
1397 case 201:\r
1398 return HTTP_STATUS_201_CREATED;\r
1399 case 202:\r
1400 return HTTP_STATUS_202_ACCEPTED;\r
1401 case 203:\r
1402 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION;\r
1403 case 204:\r
1404 return HTTP_STATUS_204_NO_CONTENT;\r
1405 case 205:\r
1406 return HTTP_STATUS_205_RESET_CONTENT;\r
1407 case 206:\r
1408 return HTTP_STATUS_206_PARTIAL_CONTENT;\r
1409 case 300:\r
1410 return HTTP_STATUS_300_MULTIPLE_CHIOCES;\r
1411 case 301:\r
1412 return HTTP_STATUS_301_MOVED_PERMANENTLY;\r
1413 case 302:\r
1414 return HTTP_STATUS_302_FOUND;\r
1415 case 303:\r
1416 return HTTP_STATUS_303_SEE_OTHER;\r
1417 case 304:\r
1418 return HTTP_STATUS_304_NOT_MODIFIED;\r
1419 case 305:\r
1420 return HTTP_STATUS_305_USE_PROXY;\r
1421 case 307:\r
1422 return HTTP_STATUS_307_TEMPORARY_REDIRECT;\r
1423 case 400:\r
1424 return HTTP_STATUS_400_BAD_REQUEST;\r
1425 case 401:\r
1426 return HTTP_STATUS_401_UNAUTHORIZED;\r
1427 case 402:\r
1428 return HTTP_STATUS_402_PAYMENT_REQUIRED;\r
1429 case 403:\r
1430 return HTTP_STATUS_403_FORBIDDEN;\r
1431 case 404:\r
1432 return HTTP_STATUS_404_NOT_FOUND;\r
1433 case 405:\r
1434 return HTTP_STATUS_405_METHOD_NOT_ALLOWED;\r
1435 case 406:\r
1436 return HTTP_STATUS_406_NOT_ACCEPTABLE;\r
1437 case 407:\r
1438 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED;\r
1439 case 408:\r
1440 return HTTP_STATUS_408_REQUEST_TIME_OUT;\r
1441 case 409:\r
1442 return HTTP_STATUS_409_CONFLICT;\r
1443 case 410:\r
1444 return HTTP_STATUS_410_GONE;\r
1445 case 411:\r
1446 return HTTP_STATUS_411_LENGTH_REQUIRED;\r
1447 case 412:\r
1448 return HTTP_STATUS_412_PRECONDITION_FAILED;\r
1449 case 413:\r
1450 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE;\r
1451 case 414:\r
1452 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE;\r
1453 case 415:\r
8cfd008e 1454 return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE;\r
47f51a06
YT
1455 case 416:\r
1456 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED;\r
1457 case 417:\r
1458 return HTTP_STATUS_417_EXPECTATION_FAILED;\r
1459 case 500:\r
1460 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR;\r
1461 case 501:\r
8cfd008e 1462 return HTTP_STATUS_501_NOT_IMPLEMENTED;\r
47f51a06
YT
1463 case 502:\r
1464 return HTTP_STATUS_502_BAD_GATEWAY;\r
1465 case 503:\r
1466 return HTTP_STATUS_503_SERVICE_UNAVAILABLE;\r
1467 case 504:\r
1468 return HTTP_STATUS_504_GATEWAY_TIME_OUT;\r
1469 case 505:\r
1470 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED;\r
1471\r
1472 default:\r
1473 return HTTP_STATUS_UNSUPPORTED_STATUS;\r
1474 }\r
1475}\r
1476\r
1477/**\r
1478 Check whether the user's token or event has already\r
b659408b 1479 been enqueue on HTTP Tx or Rx Token list.\r
47f51a06
YT
1480\r
1481 @param[in] Map The container of either user's transmit or receive\r
1482 token.\r
1483 @param[in] Item Current item to check against.\r
1484 @param[in] Context The Token to check againist.\r
1485\r
1486 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1487 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1488 context.\r
1489\r
1490**/\r
1491EFI_STATUS\r
1492EFIAPI\r
1493HttpTokenExist (\r
1494 IN NET_MAP *Map,\r
1495 IN NET_MAP_ITEM *Item,\r
1496 IN VOID *Context\r
1497 )\r
1498{\r
1499 EFI_HTTP_TOKEN *Token;\r
1500 EFI_HTTP_TOKEN *TokenInItem;\r
1501\r
1502 Token = (EFI_HTTP_TOKEN *) Context;\r
1503 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1504\r
1505 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
1506 return EFI_ACCESS_DENIED;\r
1507 }\r
1508\r
1509 return EFI_SUCCESS;\r
1510}\r
1511\r
1512/**\r
b659408b 1513 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
47f51a06 1514\r
b659408b 1515 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1516 @param[in] Item Current item to check against.\r
1517 @param[in] Context The Token to check againist.\r
1518\r
1519 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1520 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1521\r
1522**/\r
1523EFI_STATUS\r
1524EFIAPI\r
1525HttpTcpNotReady (\r
1526 IN NET_MAP *Map,\r
1527 IN NET_MAP_ITEM *Item,\r
1528 IN VOID *Context\r
1529 )\r
1530{\r
1531 HTTP_TOKEN_WRAP *ValueInItem;\r
1532\r
1533 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1534\r
1535 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1536 return EFI_NOT_READY;\r
1537 }\r
1538 \r
1539 return EFI_SUCCESS;\r
1540}\r
1541\r
1542/**\r
1543 Transmit the HTTP mssage by processing the associated HTTP token.\r
1544\r
b659408b 1545 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1546 @param[in] Item Current item to check against.\r
1547 @param[in] Context The Token to check againist.\r
1548\r
1549 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1550 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1551 queue.\r
1552\r
1553**/\r
1554EFI_STATUS\r
1555EFIAPI\r
1556HttpTcpTransmit (\r
1557 IN NET_MAP *Map,\r
1558 IN NET_MAP_ITEM *Item,\r
1559 IN VOID *Context\r
1560 )\r
1561{\r
1562 HTTP_TOKEN_WRAP *ValueInItem;\r
1563 EFI_STATUS Status;\r
1564 CHAR8 *RequestStr;\r
1565 CHAR8 *Url;\r
1566\r
1567 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1568 if (ValueInItem->TcpWrap.IsTxDone) {\r
1569 return EFI_SUCCESS;\r
1570 }\r
1571\r
1572 //\r
1573 // Parse the URI of the remote host.\r
1574 //\r
1575 Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);\r
1576 if (Url == NULL) {\r
1577 return EFI_OUT_OF_RESOURCES;\r
1578 }\r
1579\r
1580 UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);\r
1581\r
1582 //\r
1583 // Create request message.\r
1584 //\r
1585 RequestStr = HttpGenRequestString (\r
1586 ValueInItem->HttpInstance,\r
1587 ValueInItem->HttpToken->Message,\r
1588 Url\r
1589 );\r
1590 FreePool (Url);\r
1591 if (RequestStr == NULL) {\r
1592 return EFI_OUT_OF_RESOURCES;\r
1593 }\r
1594\r
1595 //\r
1596 // Transmit the request message.\r
1597 //\r
b659408b 1598 Status = HttpTransmitTcp (\r
47f51a06
YT
1599 ValueInItem->HttpInstance,\r
1600 ValueInItem,\r
1601 (UINT8*) RequestStr,\r
1602 AsciiStrLen (RequestStr)\r
1603 );\r
1604 FreePool (RequestStr);\r
1605 return Status;\r
1606}\r
1607\r
1608/**\r
1609 Receive the HTTP response by processing the associated HTTP token.\r
1610\r
b659408b 1611 @param[in] Map The container of Rx4Token or Rx6Token.\r
47f51a06
YT
1612 @param[in] Item Current item to check against.\r
1613 @param[in] Context The Token to check againist.\r
1614\r
1615 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1616 queue.\r
1617 @retval Others Other error as indicated.\r
1618\r
1619**/\r
1620EFI_STATUS\r
1621EFIAPI\r
1622HttpTcpReceive (\r
1623 IN NET_MAP *Map,\r
1624 IN NET_MAP_ITEM *Item,\r
1625 IN VOID *Context\r
1626 )\r
1627{\r
1628 //\r
1629 // Process the queued HTTP response.\r
1630 //\r
1631 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1632}\r
1633\r
b659408b
ZL
1634/**\r
1635 Receive the HTTP header by processing the associated HTTP token.\r
1636\r
1637 @param[in] HttpInstance The HTTP instance private data.\r
1638 @param[in, out] SizeofHeaders The HTTP header length.\r
1639 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
1640 \r
1641 @retval EFI_SUCCESS The HTTP header is received. \r
1642 @retval Others Other errors as indicated.\r
1643\r
1644**/\r
1645EFI_STATUS\r
1646HttpTcpReceiveHeader (\r
1647 IN HTTP_PROTOCOL *HttpInstance,\r
1648 IN OUT UINTN *SizeofHeaders,\r
1649 IN OUT UINTN *BufferSize\r
1650 )\r
1651{\r
1652 EFI_STATUS Status;\r
1653 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1654 EFI_TCP4_PROTOCOL *Tcp4;\r
1655 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1656 EFI_TCP6_PROTOCOL *Tcp6;\r
1657 CHAR8 **EndofHeader;\r
1658 CHAR8 **HttpHeaders;\r
1659 CHAR8 *Buffer;\r
1660\r
1661 ASSERT (HttpInstance != NULL);\r
1662\r
1663 EndofHeader = HttpInstance->EndofHeader;\r
1664 HttpHeaders = HttpInstance->HttpHeaders;\r
1665 Tcp4 = HttpInstance->Tcp4;\r
1666 Tcp6 = HttpInstance->Tcp6;\r
1667 Buffer = NULL;\r
1668 Rx4Token = NULL;\r
1669 Rx6Token = NULL;\r
1670 \r
1671 if (HttpInstance->LocalAddressIsIPv6) {\r
1672 ASSERT (Tcp6 != NULL);\r
1673 } else {\r
1674 ASSERT (Tcp4 != NULL);\r
1675 }\r
1676\r
1677 if (!HttpInstance->LocalAddressIsIPv6) {\r
1678 Rx4Token = &HttpInstance->Rx4Token;\r
1679 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1680 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1681 Status = EFI_OUT_OF_RESOURCES;\r
1682 return Status;\r
1683 }\r
1684 \r
1685 //\r
1686 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1687 //\r
1688 while (*EndofHeader == NULL) { \r
1689 HttpInstance->IsRxDone = FALSE;\r
1690 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1691 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1692 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1693 if (EFI_ERROR (Status)) {\r
1694 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1695 return Status;\r
1696 }\r
1697 \r
1698 while (!HttpInstance->IsRxDone) {\r
1699 Tcp4->Poll (Tcp4);\r
1700 } \r
1701 \r
1702 Status = Rx4Token->CompletionToken.Status;\r
1703 if (EFI_ERROR (Status)) {\r
1704 return Status;\r
1705 }\r
1706 \r
1707 //\r
1708 // Append the response string.\r
1709 //\r
1710 *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1711 Buffer = AllocateZeroPool (*BufferSize);\r
1712 if (Buffer == NULL) {\r
1713 Status = EFI_OUT_OF_RESOURCES;\r
1714 return Status;\r
1715 }\r
1716 \r
1717 if (*HttpHeaders != NULL) {\r
1718 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1719 FreePool (*HttpHeaders);\r
1720 }\r
1721 \r
1722 CopyMem (\r
1723 Buffer + (*SizeofHeaders),\r
1724 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1725 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1726 );\r
1727 *HttpHeaders = Buffer;\r
1728 *SizeofHeaders = *BufferSize;\r
1729 \r
1730 //\r
1731 // Check whether we received end of HTTP headers.\r
1732 //\r
1733 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); \r
1734 }\r
1735 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1736 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1737 \r
1738 } else {\r
1739 Rx6Token = &HttpInstance->Rx6Token;\r
1740 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1741 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1742 Status = EFI_OUT_OF_RESOURCES;\r
1743 return Status;\r
1744 }\r
1745 \r
1746 //\r
1747 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1748 //\r
1749 while (*EndofHeader == NULL) { \r
1750 HttpInstance->IsRxDone = FALSE;\r
1751 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1752 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1753 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1754 if (EFI_ERROR (Status)) {\r
1755 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1756 return Status;\r
1757 }\r
1758 \r
1759 while (!HttpInstance->IsRxDone) {\r
1760 Tcp6->Poll (Tcp6);\r
1761 } \r
1762 \r
1763 Status = Rx6Token->CompletionToken.Status;\r
1764 if (EFI_ERROR (Status)) {\r
1765 return Status;\r
1766 }\r
1767 \r
1768 //\r
1769 // Append the response string.\r
1770 //\r
1771 *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1772 Buffer = AllocateZeroPool (*BufferSize);\r
1773 if (Buffer == NULL) {\r
1774 Status = EFI_OUT_OF_RESOURCES;\r
1775 return Status;\r
1776 }\r
1777 \r
1778 if (*HttpHeaders != NULL) {\r
1779 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1780 FreePool (*HttpHeaders);\r
1781 }\r
1782 \r
1783 CopyMem (\r
1784 Buffer + (*SizeofHeaders),\r
1785 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1786 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1787 );\r
1788 *HttpHeaders = Buffer;\r
1789 *SizeofHeaders = *BufferSize;\r
1790 \r
1791 //\r
1792 // Check whether we received end of HTTP headers.\r
1793 //\r
1794 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1795 \r
1796 }\r
1797 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1798 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; \r
1799 } \r
1800\r
1801 //\r
1802 // Skip the CRLF after the HTTP headers.\r
1803 //\r
1804 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); \r
1805\r
1806 return EFI_SUCCESS;\r
1807}\r
1808\r
1809/**\r
1810 Receive the HTTP body by processing the associated HTTP token.\r
1811\r
1812 @param[in] Wrap The HTTP token's wrap data.\r
1813 @param[in] HttpMsg The HTTP message data.\r
1814\r
1815 @retval EFI_SUCCESS The HTTP body is received. \r
1816 @retval Others Other error as indicated.\r
1817\r
1818**/\r
1819EFI_STATUS\r
1820HttpTcpReceiveBody (\r
1821 IN HTTP_TOKEN_WRAP *Wrap,\r
1822 IN EFI_HTTP_MESSAGE *HttpMsg\r
1823 )\r
1824{\r
1825 EFI_STATUS Status;\r
1826 HTTP_PROTOCOL *HttpInstance;\r
1827 EFI_TCP6_PROTOCOL *Tcp6;\r
1828 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1829 EFI_TCP4_PROTOCOL *Tcp4;\r
1830 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1831 \r
1832 HttpInstance = Wrap->HttpInstance;\r
1833 Tcp4 = HttpInstance->Tcp4;\r
1834 Tcp6 = HttpInstance->Tcp6;\r
1835 Rx4Token = NULL;\r
1836 Rx6Token = NULL;\r
1837\r
1838 \r
1839 if (HttpInstance->LocalAddressIsIPv6) {\r
1840 ASSERT (Tcp6 != NULL);\r
1841 } else {\r
1842 ASSERT (Tcp4 != NULL);\r
1843 }\r
1844 \r
1845 if (HttpInstance->LocalAddressIsIPv6) {\r
1846 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1847 Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1848 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1849 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1850 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1851\r
1852 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1853 if (EFI_ERROR (Status)) {\r
1854 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1855 return Status;\r
1856 }\r
1857 \r
1858 } else {\r
1859 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1860 Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1861 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1862 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1863 \r
1864 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1865 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1866 if (EFI_ERROR (Status)) {\r
1867 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1868 return Status;\r
1869 }\r
1870 }\r
1871\r
1872 return EFI_SUCCESS;\r
1873\r
1874}\r
1875\r
1876/**\r
1877 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
1878\r
1879 @param[in] Wrap Pointer to HTTP token's wrap data.\r
1880 \r
1881**/\r
1882VOID\r
1883HttpTcpTokenCleanup (\r
1884 IN HTTP_TOKEN_WRAP *Wrap\r
1885 )\r
1886{ \r
1887 HTTP_PROTOCOL *HttpInstance;\r
1888 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1889 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1890\r
1b96428d 1891 ASSERT (Wrap != NULL);\r
b659408b
ZL
1892 HttpInstance = Wrap->HttpInstance;\r
1893 Rx4Token = NULL;\r
1894 Rx6Token = NULL;\r
1895 \r
1896 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d
ZL
1897 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
1898 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
1899 }\r
b659408b 1900\r
1b96428d
ZL
1901 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1902 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1903 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1904 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
b659408b 1905 }\r
1b96428d 1906 FreePool (Wrap);\r
b659408b
ZL
1907\r
1908 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
1909 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
1910 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
1911 }\r
1912\r
1913 Rx6Token = &HttpInstance->Rx6Token;\r
1914 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1915 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1916 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1917 }\r
1918 \r
1919 } else {\r
1b96428d
ZL
1920 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
1921 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
b659408b 1922 }\r
1b96428d
ZL
1923 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1924 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1925 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1926 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1927 }\r
1928 FreePool (Wrap);\r
1929\r
b659408b
ZL
1930 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
1931 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
1932 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
1933 }\r
1934 \r
1935 Rx4Token = &HttpInstance->Rx4Token;\r
1936 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1937 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1938 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1939 }\r
1940 }\r
1941\r
1942}\r
1943\r
47f51a06
YT
1944/**\r
1945 Generate HTTP request string.\r
1946\r
1947 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
1948 @param[in] Message Pointer to storage containing HTTP message data.\r
1949 @param[in] Url The URL of a remote host.\r
1950\r
1951 @return Pointer to the created HTTP request string.\r
1952 @return NULL if any error occured.\r
1953\r
1954**/\r
1955CHAR8 *\r
1956HttpGenRequestString (\r
1957 IN HTTP_PROTOCOL *HttpInstance,\r
1958 IN EFI_HTTP_MESSAGE *Message,\r
1959 IN CHAR8 *Url\r
1960 )\r
1961{\r
1962 EFI_STATUS Status;\r
1963 UINTN StrLength;\r
1964 UINT8 *Request;\r
1965 UINT8 *RequestPtr;\r
1966 UINTN HttpHdrSize;\r
1967 UINTN MsgSize;\r
1968 BOOLEAN Success;\r
1969 VOID *HttpHdr;\r
1970 EFI_HTTP_HEADER **AppendList; \r
1971 UINTN Index;\r
1972 \r
1973 ASSERT (HttpInstance != NULL);\r
1974 ASSERT (Message != NULL);\r
1975\r
1976 DEBUG ((EFI_D_ERROR, "HttpMethod - %x\n", Message->Data.Request->Method));\r
1977\r
1978 Request = NULL;\r
1979 Success = FALSE;\r
1980 HttpHdr = NULL;\r
1981 AppendList = NULL;\r
1982\r
1983 //\r
1984 // Build AppendList\r
1985 //\r
1986 AppendList = AllocateZeroPool (sizeof (EFI_HTTP_HEADER *) * (Message->HeaderCount));\r
1987 if (AppendList == NULL) {\r
1988 return NULL;\r
1989 }\r
1990\r
1991 for(Index = 0; Index < Message->HeaderCount; Index++){\r
1992 AppendList[Index] = &Message->Headers[Index];\r
1993 }\r
1994\r
5ca29abe
JW
1995 //\r
1996 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.\r
1997 //\r
1998 if (mHttpUtilities == NULL) {\r
1999 return NULL;\r
2000 }\r
2001\r
47f51a06
YT
2002 //\r
2003 // Build raw unformatted HTTP headers.\r
5ca29abe
JW
2004 //\r
2005 Status = mHttpUtilities->Build (\r
2006 mHttpUtilities,\r
2007 0,\r
2008 NULL,\r
2009 0,\r
2010 NULL,\r
2011 Message->HeaderCount,\r
2012 AppendList,\r
2013 &HttpHdrSize,\r
2014 &HttpHdr\r
2015 );\r
47f51a06
YT
2016 FreePool (AppendList);\r
2017 if (EFI_ERROR (Status) || HttpHdr == NULL) {\r
2018 return NULL;\r
2019 }\r
2020\r
2021 //\r
2022 // Calculate HTTP message length.\r
2023 //\r
2024 MsgSize = Message->BodyLength + HTTP_MAXIMUM_METHOD_LEN + AsciiStrLen (Url) + \r
2025 AsciiStrLen (HTTP_VERSION_CRLF_STR) + HttpHdrSize;\r
2026 Request = AllocateZeroPool (MsgSize);\r
2027 if (Request == NULL) {\r
2028 goto Exit;\r
2029 } \r
2030\r
2031 RequestPtr = Request;\r
2032 //\r
2033 // Construct header request\r
2034 //\r
2035 switch (Message->Data.Request->Method) {\r
2036 case HttpMethodGet:\r
2037 StrLength = sizeof (HTTP_GET_STR) - 1;\r
2038 CopyMem (RequestPtr, HTTP_GET_STR, StrLength);\r
2039 RequestPtr += StrLength;\r
2040 break;\r
2041 case HttpMethodHead:\r
2042 StrLength = sizeof (HTTP_HEAD_STR) - 1;\r
2043 CopyMem (RequestPtr, HTTP_HEAD_STR, StrLength);\r
2044 RequestPtr += StrLength;\r
2045 break;\r
2046 default:\r
2047 ASSERT (FALSE);\r
2048 goto Exit;\r
2049 }\r
2050\r
2051 StrLength = AsciiStrLen (Url);\r
2052 CopyMem (RequestPtr, Url, StrLength);\r
2053 RequestPtr += StrLength;\r
2054\r
2055 StrLength = sizeof (HTTP_VERSION_CRLF_STR) - 1;\r
2056 CopyMem (RequestPtr, HTTP_VERSION_CRLF_STR, StrLength);\r
2057 RequestPtr += StrLength;\r
2058\r
2059 //\r
2060 // Construct header\r
2061 //\r
2062 CopyMem (RequestPtr, HttpHdr, HttpHdrSize);\r
2063 RequestPtr += HttpHdrSize;\r
2064\r
2065 //\r
2066 // Construct body\r
2067 //\r
2068 if (Message->Body != NULL) {\r
2069 CopyMem (RequestPtr, Message->Body, Message->BodyLength);\r
2070 RequestPtr += Message->BodyLength;\r
2071 }\r
2072\r
2073 //\r
2074 // Done\r
2075 //\r
2076 *RequestPtr = 0;\r
2077 Success = TRUE;\r
2078 \r
2079Exit:\r
2080\r
2081 if (!Success) {\r
2082 if (Request != NULL) {\r
2083 FreePool (Request);\r
2084 }\r
2085\r
2086 Request = NULL;\r
2087 }\r
2088\r
2089 if (HttpHdr != NULL) {\r
2090 FreePool (HttpHdr);\r
2091 }\r
2092\r
2093 return (CHAR8*) Request;\r
2094}\r