]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg: Httpboot will fail the 2nd time result by wrong TCP state.
[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
568 HttpInstance = Wrap->HttpInstance;\r
569 Rx4Token = NULL;\r
570 Rx6Token = NULL;\r
571 \r
572 if (HttpInstance->LocalAddressIsIPv6) {\r
573 if (Wrap != NULL) {\r
574 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
575 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
576 } \r
577 }\r
578\r
579 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
580 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
581 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
582 }\r
583 } else {\r
584 if (Wrap != NULL) {\r
585 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
586 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
587 }\r
588 }\r
589 \r
590 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
591 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
592 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
593 }\r
594 }\r
47f51a06
YT
595}\r
596\r
597/**\r
598 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.\r
599\r
47f51a06 600 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
b659408b 601 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
47f51a06
YT
602\r
603 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully. \r
604 @retval Others Other error as indicated.\r
605\r
606**/\r
607EFI_STATUS\r
608HttpInitProtocol (\r
b659408b
ZL
609 IN OUT HTTP_PROTOCOL *HttpInstance,\r
610 IN BOOLEAN IpVersion\r
47f51a06
YT
611 )\r
612{\r
613 EFI_STATUS Status;\r
614 VOID *Interface;\r
b659408b
ZL
615 BOOLEAN UsingIpv6;\r
616 \r
617 ASSERT (HttpInstance != NULL);\r
618 UsingIpv6 = IpVersion;\r
619 \r
620 if (!UsingIpv6) {\r
621 //\r
622 // Create TCP4 child.\r
623 //\r
624 Status = NetLibCreateServiceChild (\r
625 HttpInstance->Service->ControllerHandle,\r
626 HttpInstance->Service->ImageHandle,\r
627 &gEfiTcp4ServiceBindingProtocolGuid,\r
628 &HttpInstance->Tcp4ChildHandle\r
629 );\r
47f51a06 630\r
b659408b
ZL
631 if (EFI_ERROR (Status)) {\r
632 goto ON_ERROR;\r
633 }\r
47f51a06 634\r
b659408b
ZL
635 Status = gBS->OpenProtocol (\r
636 HttpInstance->Tcp4ChildHandle,\r
637 &gEfiTcp4ProtocolGuid,\r
638 (VOID **) &Interface,\r
639 HttpInstance->Service->ImageHandle,\r
640 HttpInstance->Service->ControllerHandle,\r
641 EFI_OPEN_PROTOCOL_BY_DRIVER\r
642 );\r
643 \r
644 if (EFI_ERROR (Status)) {\r
645 goto ON_ERROR;\r
646 }\r
47f51a06 647\r
b659408b
ZL
648 Status = gBS->OpenProtocol (\r
649 HttpInstance->Tcp4ChildHandle,\r
650 &gEfiTcp4ProtocolGuid,\r
651 (VOID **) &HttpInstance->Tcp4,\r
652 HttpInstance->Service->ImageHandle,\r
653 HttpInstance->Handle,\r
654 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
655 );\r
656 if (EFI_ERROR(Status)) {\r
657 goto ON_ERROR;\r
658 }\r
47f51a06 659\r
b659408b
ZL
660 Status = gBS->OpenProtocol (\r
661 HttpInstance->Service->Tcp4ChildHandle,\r
662 &gEfiTcp4ProtocolGuid,\r
663 (VOID **) &Interface,\r
664 HttpInstance->Service->ImageHandle,\r
665 HttpInstance->Handle,\r
666 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
667 );\r
668 if (EFI_ERROR(Status)) {\r
669 goto ON_ERROR;\r
670 }\r
671 } else {\r
672 //\r
673 // Create TCP6 Child.\r
674 //\r
675 Status = NetLibCreateServiceChild (\r
676 HttpInstance->Service->ControllerHandle,\r
677 HttpInstance->Service->ImageHandle,\r
678 &gEfiTcp6ServiceBindingProtocolGuid,\r
679 &HttpInstance->Tcp6ChildHandle\r
680 );\r
47f51a06 681\r
b659408b
ZL
682 if (EFI_ERROR (Status)) {\r
683 goto ON_ERROR;\r
684 }\r
47f51a06 685\r
b659408b
ZL
686 Status = gBS->OpenProtocol (\r
687 HttpInstance->Tcp6ChildHandle,\r
688 &gEfiTcp6ProtocolGuid,\r
689 (VOID **) &Interface,\r
690 HttpInstance->Service->ImageHandle,\r
691 HttpInstance->Service->ControllerHandle,\r
692 EFI_OPEN_PROTOCOL_BY_DRIVER\r
693 );\r
694 \r
695 if (EFI_ERROR (Status)) {\r
696 goto ON_ERROR;\r
697 }\r
698\r
699 Status = gBS->OpenProtocol (\r
700 HttpInstance->Tcp6ChildHandle,\r
701 &gEfiTcp6ProtocolGuid,\r
702 (VOID **) &HttpInstance->Tcp6,\r
703 HttpInstance->Service->ImageHandle,\r
704 HttpInstance->Handle,\r
705 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
706 );\r
707 \r
708 if (EFI_ERROR(Status)) {\r
709 goto ON_ERROR;\r
710 } \r
711\r
712 Status = gBS->OpenProtocol (\r
713 HttpInstance->Service->Tcp6ChildHandle,\r
714 &gEfiTcp6ProtocolGuid,\r
715 (VOID **) &Interface,\r
716 HttpInstance->Service->ImageHandle,\r
717 HttpInstance->Handle,\r
718 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
719 );\r
47f51a06 720\r
b659408b
ZL
721 if (EFI_ERROR(Status)) {\r
722 goto ON_ERROR;\r
723 }\r
724 }\r
725 \r
51b0450e
FS
726 HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);\r
727 if (HttpInstance->Url == NULL) {\r
728 Status = EFI_OUT_OF_RESOURCES;\r
729 goto ON_ERROR;\r
730 }\r
731\r
47f51a06
YT
732 return EFI_SUCCESS;\r
733\r
734ON_ERROR:\r
735 \r
b659408b 736 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 737 gBS->CloseProtocol (\r
b659408b 738 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
739 &gEfiTcp4ProtocolGuid,\r
740 HttpInstance->Service->ImageHandle,\r
741 HttpInstance->Service->ControllerHandle\r
742 );\r
743\r
744 gBS->CloseProtocol (\r
b659408b 745 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
746 &gEfiTcp4ProtocolGuid,\r
747 HttpInstance->Service->ImageHandle,\r
748 HttpInstance->Handle\r
b659408b 749 ); \r
47f51a06
YT
750 \r
751 NetLibDestroyServiceChild (\r
752 HttpInstance->Service->ControllerHandle,\r
753 HttpInstance->Service->ImageHandle,\r
754 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 755 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
756 );\r
757 }\r
b659408b
ZL
758 \r
759 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
760 gBS->CloseProtocol (\r
761 HttpInstance->Service->Tcp4ChildHandle,\r
762 &gEfiTcp4ProtocolGuid,\r
763 HttpInstance->Service->ImageHandle,\r
764 HttpInstance->Handle\r
765 );\r
766 }\r
767 \r
768 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
769 gBS->CloseProtocol (\r
770 HttpInstance->Tcp6ChildHandle,\r
771 &gEfiTcp6ProtocolGuid,\r
772 HttpInstance->Service->ImageHandle,\r
773 HttpInstance->Service->ControllerHandle\r
774 );\r
47f51a06 775\r
b659408b
ZL
776 gBS->CloseProtocol (\r
777 HttpInstance->Tcp6ChildHandle,\r
778 &gEfiTcp6ProtocolGuid,\r
779 HttpInstance->Service->ImageHandle,\r
780 HttpInstance->Handle\r
781 );\r
782 \r
783 NetLibDestroyServiceChild (\r
784 HttpInstance->Service->ControllerHandle,\r
785 HttpInstance->Service->ImageHandle,\r
786 &gEfiTcp6ServiceBindingProtocolGuid,\r
787 HttpInstance->Tcp6ChildHandle\r
788 );\r
789 }\r
790 \r
791 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
792 gBS->CloseProtocol (\r
793 HttpInstance->Service->Tcp6ChildHandle,\r
794 &gEfiTcp6ProtocolGuid,\r
795 HttpInstance->Service->ImageHandle,\r
796 HttpInstance->Handle\r
797 );\r
798 }\r
799\r
800 return EFI_UNSUPPORTED;\r
47f51a06
YT
801 \r
802}\r
803\r
804/**\r
805 Clean up the HTTP child, release all the resources used by it.\r
806\r
807 @param[in] HttpInstance The HTTP child to clean up.\r
808\r
809**/\r
810VOID\r
811HttpCleanProtocol (\r
812 IN HTTP_PROTOCOL *HttpInstance\r
813 )\r
814{\r
815 HttpCloseConnection (HttpInstance);\r
816 \r
b659408b 817 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
818\r
819 if (HttpInstance->CacheBody != NULL) {\r
820 FreePool (HttpInstance->CacheBody);\r
821 HttpInstance->CacheBody = NULL;\r
822 HttpInstance->NextMsg = NULL;\r
823 }\r
824\r
825 if (HttpInstance->RemoteHost != NULL) {\r
826 FreePool (HttpInstance->RemoteHost);\r
827 HttpInstance->RemoteHost = NULL;\r
828 }\r
829\r
830 if (HttpInstance->MsgParser != NULL) {\r
831 HttpFreeMsgParser (HttpInstance->MsgParser);\r
832 HttpInstance->MsgParser = NULL;\r
833 }\r
b659408b 834 \r
51b0450e
FS
835 if (HttpInstance->Url != NULL) {\r
836 FreePool (HttpInstance->Url);\r
837 HttpInstance->Url = NULL;\r
838 }\r
b659408b 839 \r
47f51a06
YT
840 NetMapClean (&HttpInstance->TxTokens);\r
841 NetMapClean (&HttpInstance->RxTokens);\r
842\r
b659408b 843 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 844 gBS->CloseProtocol (\r
b659408b 845 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
846 &gEfiTcp4ProtocolGuid,\r
847 HttpInstance->Service->ImageHandle,\r
848 HttpInstance->Service->ControllerHandle\r
849 );\r
850\r
851 gBS->CloseProtocol (\r
b659408b 852 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
853 &gEfiTcp4ProtocolGuid,\r
854 HttpInstance->Service->ImageHandle,\r
855 HttpInstance->Handle\r
856 );\r
857 \r
858 NetLibDestroyServiceChild (\r
859 HttpInstance->Service->ControllerHandle,\r
860 HttpInstance->Service->ImageHandle,\r
861 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 862 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
863 );\r
864 }\r
b659408b
ZL
865\r
866 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
867 gBS->CloseProtocol (\r
868 HttpInstance->Service->Tcp4ChildHandle,\r
869 &gEfiTcp4ProtocolGuid,\r
870 HttpInstance->Service->ImageHandle,\r
871 HttpInstance->Handle\r
872 );\r
873 } \r
874\r
875 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
876 gBS->CloseProtocol (\r
877 HttpInstance->Tcp6ChildHandle,\r
878 &gEfiTcp6ProtocolGuid,\r
879 HttpInstance->Service->ImageHandle,\r
880 HttpInstance->Service->ControllerHandle\r
881 );\r
882\r
883 gBS->CloseProtocol (\r
884 HttpInstance->Tcp6ChildHandle,\r
885 &gEfiTcp6ProtocolGuid,\r
886 HttpInstance->Service->ImageHandle,\r
887 HttpInstance->Handle\r
888 );\r
889 \r
890 NetLibDestroyServiceChild (\r
891 HttpInstance->Service->ControllerHandle,\r
892 HttpInstance->Service->ImageHandle,\r
893 &gEfiTcp6ServiceBindingProtocolGuid,\r
894 HttpInstance->Tcp6ChildHandle\r
895 );\r
896 }\r
897 \r
898 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
899 gBS->CloseProtocol (\r
900 HttpInstance->Service->Tcp6ChildHandle,\r
901 &gEfiTcp6ProtocolGuid,\r
902 HttpInstance->Service->ImageHandle,\r
903 HttpInstance->Handle\r
904 );\r
905 }\r
906 \r
47f51a06
YT
907}\r
908\r
909/**\r
910 Establish TCP connection with HTTP server.\r
911\r
912 @param[in] HttpInstance The HTTP instance private data.\r
913\r
914 @retval EFI_SUCCESS The TCP connection is established.\r
915 @retval Others Other error as indicated.\r
916\r
917**/\r
918EFI_STATUS\r
919HttpCreateConnection (\r
920 IN HTTP_PROTOCOL *HttpInstance\r
921 )\r
922{\r
923 EFI_STATUS Status;\r
924\r
47f51a06
YT
925 //\r
926 // Connect to Http server\r
927 //\r
b659408b
ZL
928 if (!HttpInstance->LocalAddressIsIPv6) {\r
929 HttpInstance->IsTcp4ConnDone = FALSE;\r
930 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
931 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
932 if (EFI_ERROR (Status)) {\r
933 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
934 return Status;\r
935 }\r
936 \r
937 while (!HttpInstance->IsTcp4ConnDone) {\r
938 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
939 }\r
940 \r
941 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
942 \r
943 } else {\r
944 HttpInstance->IsTcp6ConnDone = FALSE;\r
945 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
946 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
947 if (EFI_ERROR (Status)) {\r
948 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
949 return Status;\r
950 }\r
47f51a06 951\r
b659408b
ZL
952 while(!HttpInstance->IsTcp6ConnDone) {\r
953 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
954 }\r
47f51a06 955\r
b659408b
ZL
956 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status; \r
957 }\r
958 \r
47f51a06
YT
959 if (!EFI_ERROR (Status)) {\r
960 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
961 }\r
962\r
963 return Status;\r
964}\r
965\r
966/**\r
967 Close existing TCP connection.\r
968\r
969 @param[in] HttpInstance The HTTP instance private data.\r
970\r
971 @retval EFI_SUCCESS The TCP connection is closed.\r
972 @retval Others Other error as indicated.\r
973\r
974**/\r
975EFI_STATUS\r
976HttpCloseConnection (\r
977 IN HTTP_PROTOCOL *HttpInstance\r
978 )\r
979{\r
980 EFI_STATUS Status;\r
981\r
374ecd04 982 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
47f51a06 983\r
b659408b
ZL
984 if (HttpInstance->LocalAddressIsIPv6) {\r
985 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
986 HttpInstance->IsTcp6CloseDone = FALSE;\r
987 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
988 if (EFI_ERROR (Status)) {\r
989 return Status;\r
990 }\r
991\r
992 while (!HttpInstance->IsTcp6CloseDone) {\r
993 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
994 }\r
995 \r
996 } else {\r
997 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
998 HttpInstance->IsTcp4CloseDone = FALSE;\r
999 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
1000 if (EFI_ERROR (Status)) {\r
1001 return Status;\r
1002 }\r
1003\r
1004 while (!HttpInstance->IsTcp4CloseDone) {\r
1005 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
1006 }\r
374ecd04 1007 }\r
b659408b 1008\r
47f51a06
YT
1009 }\r
1010\r
1011 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
374ecd04 1012 return EFI_SUCCESS;\r
47f51a06
YT
1013}\r
1014\r
1015/**\r
1016 Configure TCP4 protocol child.\r
1017\r
1018 @param[in] HttpInstance The HTTP instance private data.\r
1019 @param[in] Wrap The HTTP token's wrap data.\r
1020\r
1021 @retval EFI_SUCCESS The TCP4 protocol child is configured.\r
1022 @retval Others Other error as indicated.\r
1023\r
1024**/\r
1025EFI_STATUS\r
1026HttpConfigureTcp4 (\r
1027 IN HTTP_PROTOCOL *HttpInstance,\r
1028 IN HTTP_TOKEN_WRAP *Wrap\r
1029 )\r
1030{\r
1031 EFI_STATUS Status;\r
1032 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;\r
1033 EFI_TCP4_ACCESS_POINT *Tcp4AP;\r
1034 EFI_TCP4_OPTION *Tcp4Option;\r
47f51a06
YT
1035\r
1036 ASSERT (HttpInstance != NULL);\r
47f51a06
YT
1037\r
1038\r
1039 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1040 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
1041 \r
1042 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
1043 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;\r
1044 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
1045\r
1046 Tcp4AP = &Tcp4CfgData->AccessPoint;\r
1047 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;\r
1048 if (!Tcp4AP->UseDefaultAddress) {\r
1049 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
1050 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
1051 }\r
1052 \r
1053 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
1054 Tcp4AP->RemotePort = HttpInstance->RemotePort;\r
1055 Tcp4AP->ActiveFlag = TRUE;\r
1056 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);\r
1057\r
1058 Tcp4Option = Tcp4CfgData->ControlOption;\r
1059 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1060 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1061 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1062 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1063 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;\r
1064 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1065 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1066 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1067 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1068 Tcp4Option->EnableNagle = TRUE;\r
1069 Tcp4CfgData->ControlOption = Tcp4Option;\r
1070\r
1071 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);\r
1072 if (EFI_ERROR (Status)) {\r
1073 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status));\r
1074 return Status;\r
1075 }\r
1076\r
b659408b
ZL
1077 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1078 if (EFI_ERROR (Status)) {\r
1079 return Status;\r
1080 }\r
1081\r
1082 Status = HttpCreateTcpTxEvent (Wrap);\r
1083 if (EFI_ERROR (Status)) {\r
1084 return Status;\r
1085 }\r
1086\r
1087 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1088\r
1089 return EFI_SUCCESS;\r
1090}\r
1091\r
1092/**\r
1093 Configure TCP6 protocol child.\r
1094\r
1095 @param[in] HttpInstance The HTTP instance private data.\r
1096 @param[in] Wrap The HTTP token's wrap data.\r
1097\r
1098 @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
1099 @retval Others Other error as indicated.\r
1100\r
1101**/\r
1102EFI_STATUS\r
1103HttpConfigureTcp6 (\r
1104 IN HTTP_PROTOCOL *HttpInstance,\r
1105 IN HTTP_TOKEN_WRAP *Wrap\r
1106 )\r
1107{\r
1108 EFI_STATUS Status;\r
1109 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
1110 EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
1111 EFI_TCP6_OPTION *Tcp6Option;\r
1112 \r
1113 ASSERT (HttpInstance != NULL);\r
1114 \r
1115 Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
1116 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
1117\r
1118 Tcp6CfgData->TrafficClass = 0;\r
1119 Tcp6CfgData->HopLimit = 255;\r
1120 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
1121 \r
1122 Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
1123 Tcp6Ap->ActiveFlag = TRUE;\r
1124 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
1125 Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
1126 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
1127 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
1128\r
1129 Tcp6Option = Tcp6CfgData->ControlOption;\r
1130 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1131 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1132 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1133 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1134 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
1135 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1136 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1137 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1138 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1139 Tcp6Option->EnableNagle = TRUE;\r
1140\r
1141 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1142 if (EFI_ERROR (Status)) {\r
1143 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
1144 return Status;\r
1145 }\r
1146 \r
1147 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
1148 if (EFI_ERROR (Status)) {\r
1149 return Status;\r
1150 }\r
1151\r
b659408b 1152 Status = HttpCreateTcpTxEvent (Wrap);\r
47f51a06
YT
1153 if (EFI_ERROR (Status)) {\r
1154 return Status;\r
1155 }\r
1156\r
1157 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1158\r
1159 return EFI_SUCCESS;\r
b659408b 1160 \r
47f51a06
YT
1161}\r
1162\r
1163/**\r
b659408b 1164 Check existing TCP connection, if in error state, recover TCP4 connection.\r
47f51a06
YT
1165\r
1166 @param[in] HttpInstance The HTTP instance private data.\r
1167\r
1168 @retval EFI_SUCCESS The TCP connection is established.\r
1169 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1170 @retval Others Other error as indicated.\r
1171\r
1172**/\r
1173EFI_STATUS\r
1174HttpConnectTcp4 (\r
1175 IN HTTP_PROTOCOL *HttpInstance\r
1176 )\r
1177{\r
1178 EFI_STATUS Status;\r
1179 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
1180\r
1181\r
a2e61982 1182 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
47f51a06
YT
1183 return EFI_NOT_READY;\r
1184 }\r
1185\r
1186 Status = HttpInstance->Tcp4->GetModeData(\r
1187 HttpInstance->Tcp4, \r
1188 &Tcp4State, \r
1189 NULL,\r
1190 NULL,\r
1191 NULL,\r
1192 NULL\r
1193 );\r
1194 if (EFI_ERROR(Status)){\r
1195 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
1196 return Status;\r
1197 }\r
1198\r
a2e61982
ZL
1199 if (Tcp4State == Tcp4StateEstablished) {\r
1200 return EFI_SUCCESS;\r
1201 } else if (Tcp4State > Tcp4StateEstablished ) {\r
47f51a06 1202 HttpCloseConnection(HttpInstance);\r
a2e61982 1203 }\r
47f51a06
YT
1204\r
1205 return HttpCreateConnection (HttpInstance);\r
1206}\r
1207\r
1208/**\r
b659408b
ZL
1209 Check existing TCP connection, if in error state, recover TCP6 connection.\r
1210\r
1211 @param[in] HttpInstance The HTTP instance private data.\r
1212\r
1213 @retval EFI_SUCCESS The TCP connection is established.\r
1214 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1215 @retval Others Other error as indicated.\r
1216\r
1217**/\r
1218EFI_STATUS\r
1219HttpConnectTcp6 (\r
1220 IN HTTP_PROTOCOL *HttpInstance\r
1221 )\r
1222{\r
1223 EFI_STATUS Status;\r
1224 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
1225\r
a2e61982 1226 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
b659408b
ZL
1227 return EFI_NOT_READY;\r
1228 }\r
1229\r
1230 Status = HttpInstance->Tcp6->GetModeData (\r
1231 HttpInstance->Tcp6,\r
1232 &Tcp6State,\r
1233 NULL,\r
1234 NULL,\r
1235 NULL,\r
1236 NULL\r
1237 );\r
1238 \r
1239 if (EFI_ERROR(Status)){\r
1240 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1241 return Status;\r
1242 }\r
1243\r
a2e61982
ZL
1244 if (Tcp6State == Tcp6StateEstablished) {\r
1245 return EFI_SUCCESS;\r
1246 } else if (Tcp6State > Tcp6StateEstablished ) {\r
1247 HttpCloseConnection(HttpInstance);\r
b659408b
ZL
1248 }\r
1249\r
1250 return HttpCreateConnection (HttpInstance);\r
1251}\r
1252\r
1253/**\r
1254 Initialize TCP related data.\r
1255\r
1256 @param[in] HttpInstance The HTTP instance private data.\r
1257 @param[in] Wrap The HTTP token's wrap data.\r
a2e61982 1258 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.\r
b659408b
ZL
1259\r
1260 @retval EFI_SUCCESS The initialization of TCP instance is done. \r
1261 @retval Others Other error as indicated.\r
1262\r
1263**/\r
1264EFI_STATUS\r
1265HttpInitTcp (\r
1266 IN HTTP_PROTOCOL *HttpInstance,\r
a2e61982
ZL
1267 IN HTTP_TOKEN_WRAP *Wrap,\r
1268 IN BOOLEAN Configure\r
b659408b
ZL
1269 )\r
1270{\r
1271 EFI_STATUS Status;\r
1272 ASSERT (HttpInstance != NULL);\r
1273\r
1274 if (!HttpInstance->LocalAddressIsIPv6) {\r
1275 //\r
1276 // Configure TCP instance.\r
1277 //\r
a2e61982
ZL
1278 if (Configure) {\r
1279 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1280 if (EFI_ERROR (Status)) {\r
1281 return Status;\r
1282 }\r
b659408b 1283 }\r
a2e61982 1284\r
b659408b
ZL
1285 //\r
1286 // Connect TCP.\r
1287 //\r
1288 Status = HttpConnectTcp4 (HttpInstance);\r
1289 if (EFI_ERROR (Status)) {\r
1290 return Status;\r
1291 }\r
1292 } else {\r
1293 //\r
1294 // Configure TCP instance.\r
1295 //\r
a2e61982
ZL
1296 if (Configure) {\r
1297 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1298 if (EFI_ERROR (Status)) {\r
1299 return Status;\r
1300 }\r
b659408b 1301 }\r
a2e61982 1302\r
b659408b
ZL
1303 //\r
1304 // Connect TCP.\r
1305 //\r
1306 Status = HttpConnectTcp6 (HttpInstance);\r
1307 if (EFI_ERROR (Status)) {\r
1308 return Status;\r
1309 }\r
1310 }\r
1311 \r
1312 return EFI_SUCCESS;\r
1313 \r
1314}\r
1315\r
1316/**\r
1317 Send the HTTP message through TCP4 or TCP6.\r
47f51a06
YT
1318\r
1319 @param[in] HttpInstance The HTTP instance private data.\r
1320 @param[in] Wrap The HTTP token's wrap data.\r
1321 @param[in] TxString Buffer containing the HTTP message string.\r
1322 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1323\r
1324 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1325 @retval Others Other error as indicated.\r
1326\r
1327**/\r
1328EFI_STATUS\r
b659408b 1329HttpTransmitTcp (\r
47f51a06
YT
1330 IN HTTP_PROTOCOL *HttpInstance,\r
1331 IN HTTP_TOKEN_WRAP *Wrap,\r
1332 IN UINT8 *TxString,\r
1333 IN UINTN TxStringLen\r
1334 )\r
1335{\r
1336 EFI_STATUS Status;\r
b659408b 1337 EFI_TCP4_IO_TOKEN *Tx4Token;\r
47f51a06 1338 EFI_TCP4_PROTOCOL *Tcp4;\r
b659408b
ZL
1339 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1340 EFI_TCP6_PROTOCOL *Tcp6;\r
47f51a06 1341 \r
b659408b
ZL
1342 if (!HttpInstance->LocalAddressIsIPv6) { \r
1343 Tcp4 = HttpInstance->Tcp4;\r
1344 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
1345 \r
1346 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1347 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1348 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1349 Tx4Token->CompletionToken.Status = EFI_NOT_READY; \r
1350 \r
1351 Wrap->TcpWrap.IsTxDone = FALSE;\r
1352 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1353 if (EFI_ERROR (Status)) {\r
1354 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1355 return Status;\r
1356 }\r
47f51a06 1357\r
b659408b
ZL
1358 } else {\r
1359 Tcp6 = HttpInstance->Tcp6;\r
1360 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
47f51a06 1361\r
b659408b
ZL
1362 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1363 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1364 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1365 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1366\r
1367 Wrap->TcpWrap.IsTxDone = FALSE;\r
1368 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1369 if (EFI_ERROR (Status)) {\r
1370 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1371 return Status;\r
1372 }\r
47f51a06 1373 }\r
b659408b 1374 \r
47f51a06
YT
1375\r
1376 return Status;\r
1377}\r
1378\r
1379/**\r
1380 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined \r
1381 in UEFI 2.5 specification.\r
1382\r
1383 @param[in] StatusCode The status code value in HTTP message.\r
1384\r
1385 @return Value defined in EFI_HTTP_STATUS_CODE .\r
1386\r
1387**/\r
1388EFI_HTTP_STATUS_CODE\r
1389HttpMappingToStatusCode (\r
1390 IN UINTN StatusCode\r
1391 ) \r
1392{\r
1393 switch (StatusCode) {\r
1394 case 100:\r
1395 return HTTP_STATUS_100_CONTINUE;\r
1396 case 101:\r
1397 return HTTP_STATUS_101_SWITCHING_PROTOCOLS;\r
1398 case 200:\r
1399 return HTTP_STATUS_200_OK;\r
1400 case 201:\r
1401 return HTTP_STATUS_201_CREATED;\r
1402 case 202:\r
1403 return HTTP_STATUS_202_ACCEPTED;\r
1404 case 203:\r
1405 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION;\r
1406 case 204:\r
1407 return HTTP_STATUS_204_NO_CONTENT;\r
1408 case 205:\r
1409 return HTTP_STATUS_205_RESET_CONTENT;\r
1410 case 206:\r
1411 return HTTP_STATUS_206_PARTIAL_CONTENT;\r
1412 case 300:\r
1413 return HTTP_STATUS_300_MULTIPLE_CHIOCES;\r
1414 case 301:\r
1415 return HTTP_STATUS_301_MOVED_PERMANENTLY;\r
1416 case 302:\r
1417 return HTTP_STATUS_302_FOUND;\r
1418 case 303:\r
1419 return HTTP_STATUS_303_SEE_OTHER;\r
1420 case 304:\r
1421 return HTTP_STATUS_304_NOT_MODIFIED;\r
1422 case 305:\r
1423 return HTTP_STATUS_305_USE_PROXY;\r
1424 case 307:\r
1425 return HTTP_STATUS_307_TEMPORARY_REDIRECT;\r
1426 case 400:\r
1427 return HTTP_STATUS_400_BAD_REQUEST;\r
1428 case 401:\r
1429 return HTTP_STATUS_401_UNAUTHORIZED;\r
1430 case 402:\r
1431 return HTTP_STATUS_402_PAYMENT_REQUIRED;\r
1432 case 403:\r
1433 return HTTP_STATUS_403_FORBIDDEN;\r
1434 case 404:\r
1435 return HTTP_STATUS_404_NOT_FOUND;\r
1436 case 405:\r
1437 return HTTP_STATUS_405_METHOD_NOT_ALLOWED;\r
1438 case 406:\r
1439 return HTTP_STATUS_406_NOT_ACCEPTABLE;\r
1440 case 407:\r
1441 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED;\r
1442 case 408:\r
1443 return HTTP_STATUS_408_REQUEST_TIME_OUT;\r
1444 case 409:\r
1445 return HTTP_STATUS_409_CONFLICT;\r
1446 case 410:\r
1447 return HTTP_STATUS_410_GONE;\r
1448 case 411:\r
1449 return HTTP_STATUS_411_LENGTH_REQUIRED;\r
1450 case 412:\r
1451 return HTTP_STATUS_412_PRECONDITION_FAILED;\r
1452 case 413:\r
1453 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE;\r
1454 case 414:\r
1455 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE;\r
1456 case 415:\r
8cfd008e 1457 return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE;\r
47f51a06
YT
1458 case 416:\r
1459 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED;\r
1460 case 417:\r
1461 return HTTP_STATUS_417_EXPECTATION_FAILED;\r
1462 case 500:\r
1463 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR;\r
1464 case 501:\r
8cfd008e 1465 return HTTP_STATUS_501_NOT_IMPLEMENTED;\r
47f51a06
YT
1466 case 502:\r
1467 return HTTP_STATUS_502_BAD_GATEWAY;\r
1468 case 503:\r
1469 return HTTP_STATUS_503_SERVICE_UNAVAILABLE;\r
1470 case 504:\r
1471 return HTTP_STATUS_504_GATEWAY_TIME_OUT;\r
1472 case 505:\r
1473 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED;\r
1474\r
1475 default:\r
1476 return HTTP_STATUS_UNSUPPORTED_STATUS;\r
1477 }\r
1478}\r
1479\r
1480/**\r
1481 Check whether the user's token or event has already\r
b659408b 1482 been enqueue on HTTP Tx or Rx Token list.\r
47f51a06
YT
1483\r
1484 @param[in] Map The container of either user's transmit or receive\r
1485 token.\r
1486 @param[in] Item Current item to check against.\r
1487 @param[in] Context The Token to check againist.\r
1488\r
1489 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1490 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1491 context.\r
1492\r
1493**/\r
1494EFI_STATUS\r
1495EFIAPI\r
1496HttpTokenExist (\r
1497 IN NET_MAP *Map,\r
1498 IN NET_MAP_ITEM *Item,\r
1499 IN VOID *Context\r
1500 )\r
1501{\r
1502 EFI_HTTP_TOKEN *Token;\r
1503 EFI_HTTP_TOKEN *TokenInItem;\r
1504\r
1505 Token = (EFI_HTTP_TOKEN *) Context;\r
1506 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1507\r
1508 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
1509 return EFI_ACCESS_DENIED;\r
1510 }\r
1511\r
1512 return EFI_SUCCESS;\r
1513}\r
1514\r
1515/**\r
b659408b 1516 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
47f51a06 1517\r
b659408b 1518 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1519 @param[in] Item Current item to check against.\r
1520 @param[in] Context The Token to check againist.\r
1521\r
1522 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1523 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1524\r
1525**/\r
1526EFI_STATUS\r
1527EFIAPI\r
1528HttpTcpNotReady (\r
1529 IN NET_MAP *Map,\r
1530 IN NET_MAP_ITEM *Item,\r
1531 IN VOID *Context\r
1532 )\r
1533{\r
1534 HTTP_TOKEN_WRAP *ValueInItem;\r
1535\r
1536 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1537\r
1538 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1539 return EFI_NOT_READY;\r
1540 }\r
1541 \r
1542 return EFI_SUCCESS;\r
1543}\r
1544\r
1545/**\r
1546 Transmit the HTTP mssage by processing the associated HTTP token.\r
1547\r
b659408b 1548 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1549 @param[in] Item Current item to check against.\r
1550 @param[in] Context The Token to check againist.\r
1551\r
1552 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1553 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1554 queue.\r
1555\r
1556**/\r
1557EFI_STATUS\r
1558EFIAPI\r
1559HttpTcpTransmit (\r
1560 IN NET_MAP *Map,\r
1561 IN NET_MAP_ITEM *Item,\r
1562 IN VOID *Context\r
1563 )\r
1564{\r
1565 HTTP_TOKEN_WRAP *ValueInItem;\r
1566 EFI_STATUS Status;\r
1567 CHAR8 *RequestStr;\r
1568 CHAR8 *Url;\r
1569\r
1570 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1571 if (ValueInItem->TcpWrap.IsTxDone) {\r
1572 return EFI_SUCCESS;\r
1573 }\r
1574\r
1575 //\r
1576 // Parse the URI of the remote host.\r
1577 //\r
1578 Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);\r
1579 if (Url == NULL) {\r
1580 return EFI_OUT_OF_RESOURCES;\r
1581 }\r
1582\r
1583 UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);\r
1584\r
1585 //\r
1586 // Create request message.\r
1587 //\r
1588 RequestStr = HttpGenRequestString (\r
1589 ValueInItem->HttpInstance,\r
1590 ValueInItem->HttpToken->Message,\r
1591 Url\r
1592 );\r
1593 FreePool (Url);\r
1594 if (RequestStr == NULL) {\r
1595 return EFI_OUT_OF_RESOURCES;\r
1596 }\r
1597\r
1598 //\r
1599 // Transmit the request message.\r
1600 //\r
b659408b 1601 Status = HttpTransmitTcp (\r
47f51a06
YT
1602 ValueInItem->HttpInstance,\r
1603 ValueInItem,\r
1604 (UINT8*) RequestStr,\r
1605 AsciiStrLen (RequestStr)\r
1606 );\r
1607 FreePool (RequestStr);\r
1608 return Status;\r
1609}\r
1610\r
1611/**\r
1612 Receive the HTTP response by processing the associated HTTP token.\r
1613\r
b659408b 1614 @param[in] Map The container of Rx4Token or Rx6Token.\r
47f51a06
YT
1615 @param[in] Item Current item to check against.\r
1616 @param[in] Context The Token to check againist.\r
1617\r
1618 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1619 queue.\r
1620 @retval Others Other error as indicated.\r
1621\r
1622**/\r
1623EFI_STATUS\r
1624EFIAPI\r
1625HttpTcpReceive (\r
1626 IN NET_MAP *Map,\r
1627 IN NET_MAP_ITEM *Item,\r
1628 IN VOID *Context\r
1629 )\r
1630{\r
1631 //\r
1632 // Process the queued HTTP response.\r
1633 //\r
1634 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1635}\r
1636\r
b659408b
ZL
1637/**\r
1638 Receive the HTTP header by processing the associated HTTP token.\r
1639\r
1640 @param[in] HttpInstance The HTTP instance private data.\r
1641 @param[in, out] SizeofHeaders The HTTP header length.\r
1642 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
1643 \r
1644 @retval EFI_SUCCESS The HTTP header is received. \r
1645 @retval Others Other errors as indicated.\r
1646\r
1647**/\r
1648EFI_STATUS\r
1649HttpTcpReceiveHeader (\r
1650 IN HTTP_PROTOCOL *HttpInstance,\r
1651 IN OUT UINTN *SizeofHeaders,\r
1652 IN OUT UINTN *BufferSize\r
1653 )\r
1654{\r
1655 EFI_STATUS Status;\r
1656 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1657 EFI_TCP4_PROTOCOL *Tcp4;\r
1658 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1659 EFI_TCP6_PROTOCOL *Tcp6;\r
1660 CHAR8 **EndofHeader;\r
1661 CHAR8 **HttpHeaders;\r
1662 CHAR8 *Buffer;\r
1663\r
1664 ASSERT (HttpInstance != NULL);\r
1665\r
1666 EndofHeader = HttpInstance->EndofHeader;\r
1667 HttpHeaders = HttpInstance->HttpHeaders;\r
1668 Tcp4 = HttpInstance->Tcp4;\r
1669 Tcp6 = HttpInstance->Tcp6;\r
1670 Buffer = NULL;\r
1671 Rx4Token = NULL;\r
1672 Rx6Token = NULL;\r
1673 \r
1674 if (HttpInstance->LocalAddressIsIPv6) {\r
1675 ASSERT (Tcp6 != NULL);\r
1676 } else {\r
1677 ASSERT (Tcp4 != NULL);\r
1678 }\r
1679\r
1680 if (!HttpInstance->LocalAddressIsIPv6) {\r
1681 Rx4Token = &HttpInstance->Rx4Token;\r
1682 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1683 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1684 Status = EFI_OUT_OF_RESOURCES;\r
1685 return Status;\r
1686 }\r
1687 \r
1688 //\r
1689 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1690 //\r
1691 while (*EndofHeader == NULL) { \r
1692 HttpInstance->IsRxDone = FALSE;\r
1693 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1694 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1695 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1696 if (EFI_ERROR (Status)) {\r
1697 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1698 return Status;\r
1699 }\r
1700 \r
1701 while (!HttpInstance->IsRxDone) {\r
1702 Tcp4->Poll (Tcp4);\r
1703 } \r
1704 \r
1705 Status = Rx4Token->CompletionToken.Status;\r
1706 if (EFI_ERROR (Status)) {\r
1707 return Status;\r
1708 }\r
1709 \r
1710 //\r
1711 // Append the response string.\r
1712 //\r
1713 *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1714 Buffer = AllocateZeroPool (*BufferSize);\r
1715 if (Buffer == NULL) {\r
1716 Status = EFI_OUT_OF_RESOURCES;\r
1717 return Status;\r
1718 }\r
1719 \r
1720 if (*HttpHeaders != NULL) {\r
1721 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1722 FreePool (*HttpHeaders);\r
1723 }\r
1724 \r
1725 CopyMem (\r
1726 Buffer + (*SizeofHeaders),\r
1727 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1728 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1729 );\r
1730 *HttpHeaders = Buffer;\r
1731 *SizeofHeaders = *BufferSize;\r
1732 \r
1733 //\r
1734 // Check whether we received end of HTTP headers.\r
1735 //\r
1736 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); \r
1737 }\r
1738 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1739 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1740 \r
1741 } else {\r
1742 Rx6Token = &HttpInstance->Rx6Token;\r
1743 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1744 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1745 Status = EFI_OUT_OF_RESOURCES;\r
1746 return Status;\r
1747 }\r
1748 \r
1749 //\r
1750 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1751 //\r
1752 while (*EndofHeader == NULL) { \r
1753 HttpInstance->IsRxDone = FALSE;\r
1754 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1755 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1756 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1757 if (EFI_ERROR (Status)) {\r
1758 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1759 return Status;\r
1760 }\r
1761 \r
1762 while (!HttpInstance->IsRxDone) {\r
1763 Tcp6->Poll (Tcp6);\r
1764 } \r
1765 \r
1766 Status = Rx6Token->CompletionToken.Status;\r
1767 if (EFI_ERROR (Status)) {\r
1768 return Status;\r
1769 }\r
1770 \r
1771 //\r
1772 // Append the response string.\r
1773 //\r
1774 *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1775 Buffer = AllocateZeroPool (*BufferSize);\r
1776 if (Buffer == NULL) {\r
1777 Status = EFI_OUT_OF_RESOURCES;\r
1778 return Status;\r
1779 }\r
1780 \r
1781 if (*HttpHeaders != NULL) {\r
1782 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1783 FreePool (*HttpHeaders);\r
1784 }\r
1785 \r
1786 CopyMem (\r
1787 Buffer + (*SizeofHeaders),\r
1788 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1789 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1790 );\r
1791 *HttpHeaders = Buffer;\r
1792 *SizeofHeaders = *BufferSize;\r
1793 \r
1794 //\r
1795 // Check whether we received end of HTTP headers.\r
1796 //\r
1797 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1798 \r
1799 }\r
1800 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1801 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; \r
1802 } \r
1803\r
1804 //\r
1805 // Skip the CRLF after the HTTP headers.\r
1806 //\r
1807 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); \r
1808\r
1809 return EFI_SUCCESS;\r
1810}\r
1811\r
1812/**\r
1813 Receive the HTTP body by processing the associated HTTP token.\r
1814\r
1815 @param[in] Wrap The HTTP token's wrap data.\r
1816 @param[in] HttpMsg The HTTP message data.\r
1817\r
1818 @retval EFI_SUCCESS The HTTP body is received. \r
1819 @retval Others Other error as indicated.\r
1820\r
1821**/\r
1822EFI_STATUS\r
1823HttpTcpReceiveBody (\r
1824 IN HTTP_TOKEN_WRAP *Wrap,\r
1825 IN EFI_HTTP_MESSAGE *HttpMsg\r
1826 )\r
1827{\r
1828 EFI_STATUS Status;\r
1829 HTTP_PROTOCOL *HttpInstance;\r
1830 EFI_TCP6_PROTOCOL *Tcp6;\r
1831 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1832 EFI_TCP4_PROTOCOL *Tcp4;\r
1833 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1834 \r
1835 HttpInstance = Wrap->HttpInstance;\r
1836 Tcp4 = HttpInstance->Tcp4;\r
1837 Tcp6 = HttpInstance->Tcp6;\r
1838 Rx4Token = NULL;\r
1839 Rx6Token = NULL;\r
1840\r
1841 \r
1842 if (HttpInstance->LocalAddressIsIPv6) {\r
1843 ASSERT (Tcp6 != NULL);\r
1844 } else {\r
1845 ASSERT (Tcp4 != NULL);\r
1846 }\r
1847 \r
1848 if (HttpInstance->LocalAddressIsIPv6) {\r
1849 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1850 Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1851 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1852 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1853 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1854\r
1855 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1856 if (EFI_ERROR (Status)) {\r
1857 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1858 return Status;\r
1859 }\r
1860 \r
1861 } else {\r
1862 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1863 Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1864 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1865 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1866 \r
1867 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1868 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1869 if (EFI_ERROR (Status)) {\r
1870 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1871 return Status;\r
1872 }\r
1873 }\r
1874\r
1875 return EFI_SUCCESS;\r
1876\r
1877}\r
1878\r
1879/**\r
1880 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
1881\r
1882 @param[in] Wrap Pointer to HTTP token's wrap data.\r
1883 \r
1884**/\r
1885VOID\r
1886HttpTcpTokenCleanup (\r
1887 IN HTTP_TOKEN_WRAP *Wrap\r
1888 )\r
1889{ \r
1890 HTTP_PROTOCOL *HttpInstance;\r
1891 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1892 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1893\r
1894 HttpInstance = Wrap->HttpInstance;\r
1895 Rx4Token = NULL;\r
1896 Rx6Token = NULL;\r
1897 \r
1898 if (HttpInstance->LocalAddressIsIPv6) {\r
1899 if (Wrap != NULL) {\r
1900 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
1901 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
1902 }\r
1903\r
1904 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1905 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1906 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1907 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1908 }\r
1909 FreePool (Wrap); \r
1910 }\r
1911\r
1912 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
1913 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
1914 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
1915 }\r
1916\r
1917 Rx6Token = &HttpInstance->Rx6Token;\r
1918 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1919 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1920 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1921 }\r
1922 \r
1923 } else {\r
1924 if (Wrap != NULL) {\r
1925 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
1926 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
1927 }\r
1928 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1929 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1930 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1931 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1932 }\r
1933 FreePool (Wrap);\r
1934 }\r
1935 \r
1936 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
1937 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
1938 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
1939 }\r
1940 \r
1941 Rx4Token = &HttpInstance->Rx4Token;\r
1942 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1943 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1944 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1945 }\r
1946 }\r
1947\r
1948}\r
1949\r
47f51a06
YT
1950/**\r
1951 Generate HTTP request string.\r
1952\r
1953 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
1954 @param[in] Message Pointer to storage containing HTTP message data.\r
1955 @param[in] Url The URL of a remote host.\r
1956\r
1957 @return Pointer to the created HTTP request string.\r
1958 @return NULL if any error occured.\r
1959\r
1960**/\r
1961CHAR8 *\r
1962HttpGenRequestString (\r
1963 IN HTTP_PROTOCOL *HttpInstance,\r
1964 IN EFI_HTTP_MESSAGE *Message,\r
1965 IN CHAR8 *Url\r
1966 )\r
1967{\r
1968 EFI_STATUS Status;\r
1969 UINTN StrLength;\r
1970 UINT8 *Request;\r
1971 UINT8 *RequestPtr;\r
1972 UINTN HttpHdrSize;\r
1973 UINTN MsgSize;\r
1974 BOOLEAN Success;\r
1975 VOID *HttpHdr;\r
1976 EFI_HTTP_HEADER **AppendList; \r
1977 UINTN Index;\r
1978 \r
1979 ASSERT (HttpInstance != NULL);\r
1980 ASSERT (Message != NULL);\r
1981\r
1982 DEBUG ((EFI_D_ERROR, "HttpMethod - %x\n", Message->Data.Request->Method));\r
1983\r
1984 Request = NULL;\r
1985 Success = FALSE;\r
1986 HttpHdr = NULL;\r
1987 AppendList = NULL;\r
1988\r
1989 //\r
1990 // Build AppendList\r
1991 //\r
1992 AppendList = AllocateZeroPool (sizeof (EFI_HTTP_HEADER *) * (Message->HeaderCount));\r
1993 if (AppendList == NULL) {\r
1994 return NULL;\r
1995 }\r
1996\r
1997 for(Index = 0; Index < Message->HeaderCount; Index++){\r
1998 AppendList[Index] = &Message->Headers[Index];\r
1999 }\r
2000\r
5ca29abe
JW
2001 //\r
2002 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.\r
2003 //\r
2004 if (mHttpUtilities == NULL) {\r
2005 return NULL;\r
2006 }\r
2007\r
47f51a06
YT
2008 //\r
2009 // Build raw unformatted HTTP headers.\r
5ca29abe
JW
2010 //\r
2011 Status = mHttpUtilities->Build (\r
2012 mHttpUtilities,\r
2013 0,\r
2014 NULL,\r
2015 0,\r
2016 NULL,\r
2017 Message->HeaderCount,\r
2018 AppendList,\r
2019 &HttpHdrSize,\r
2020 &HttpHdr\r
2021 );\r
47f51a06
YT
2022 FreePool (AppendList);\r
2023 if (EFI_ERROR (Status) || HttpHdr == NULL) {\r
2024 return NULL;\r
2025 }\r
2026\r
2027 //\r
2028 // Calculate HTTP message length.\r
2029 //\r
2030 MsgSize = Message->BodyLength + HTTP_MAXIMUM_METHOD_LEN + AsciiStrLen (Url) + \r
2031 AsciiStrLen (HTTP_VERSION_CRLF_STR) + HttpHdrSize;\r
2032 Request = AllocateZeroPool (MsgSize);\r
2033 if (Request == NULL) {\r
2034 goto Exit;\r
2035 } \r
2036\r
2037 RequestPtr = Request;\r
2038 //\r
2039 // Construct header request\r
2040 //\r
2041 switch (Message->Data.Request->Method) {\r
2042 case HttpMethodGet:\r
2043 StrLength = sizeof (HTTP_GET_STR) - 1;\r
2044 CopyMem (RequestPtr, HTTP_GET_STR, StrLength);\r
2045 RequestPtr += StrLength;\r
2046 break;\r
2047 case HttpMethodHead:\r
2048 StrLength = sizeof (HTTP_HEAD_STR) - 1;\r
2049 CopyMem (RequestPtr, HTTP_HEAD_STR, StrLength);\r
2050 RequestPtr += StrLength;\r
2051 break;\r
2052 default:\r
2053 ASSERT (FALSE);\r
2054 goto Exit;\r
2055 }\r
2056\r
2057 StrLength = AsciiStrLen (Url);\r
2058 CopyMem (RequestPtr, Url, StrLength);\r
2059 RequestPtr += StrLength;\r
2060\r
2061 StrLength = sizeof (HTTP_VERSION_CRLF_STR) - 1;\r
2062 CopyMem (RequestPtr, HTTP_VERSION_CRLF_STR, StrLength);\r
2063 RequestPtr += StrLength;\r
2064\r
2065 //\r
2066 // Construct header\r
2067 //\r
2068 CopyMem (RequestPtr, HttpHdr, HttpHdrSize);\r
2069 RequestPtr += HttpHdrSize;\r
2070\r
2071 //\r
2072 // Construct body\r
2073 //\r
2074 if (Message->Body != NULL) {\r
2075 CopyMem (RequestPtr, Message->Body, Message->BodyLength);\r
2076 RequestPtr += Message->BodyLength;\r
2077 }\r
2078\r
2079 //\r
2080 // Done\r
2081 //\r
2082 *RequestPtr = 0;\r
2083 Success = TRUE;\r
2084 \r
2085Exit:\r
2086\r
2087 if (!Success) {\r
2088 if (Request != NULL) {\r
2089 FreePool (Request);\r
2090 }\r
2091\r
2092 Request = NULL;\r
2093 }\r
2094\r
2095 if (HttpHdr != NULL) {\r
2096 FreePool (HttpHdr);\r
2097 }\r
2098\r
2099 return (CHAR8*) Request;\r
2100}\r