]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg:Enable Http Boot over Ipv6 stack
[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
1182 if (HttpInstance->State != HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
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
1199 if (Tcp4State > Tcp4StateEstablished) {\r
1200 HttpCloseConnection(HttpInstance);\r
1201 } \r
1202\r
1203 return HttpCreateConnection (HttpInstance);\r
1204}\r
1205\r
1206/**\r
b659408b
ZL
1207 Check existing TCP connection, if in error state, recover TCP6 connection.\r
1208\r
1209 @param[in] HttpInstance The HTTP instance private data.\r
1210\r
1211 @retval EFI_SUCCESS The TCP connection is established.\r
1212 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1213 @retval Others Other error as indicated.\r
1214\r
1215**/\r
1216EFI_STATUS\r
1217HttpConnectTcp6 (\r
1218 IN HTTP_PROTOCOL *HttpInstance\r
1219 )\r
1220{\r
1221 EFI_STATUS Status;\r
1222 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
1223\r
1224 if (HttpInstance->State != HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
1225 return EFI_NOT_READY;\r
1226 }\r
1227\r
1228 Status = HttpInstance->Tcp6->GetModeData (\r
1229 HttpInstance->Tcp6,\r
1230 &Tcp6State,\r
1231 NULL,\r
1232 NULL,\r
1233 NULL,\r
1234 NULL\r
1235 );\r
1236 \r
1237 if (EFI_ERROR(Status)){\r
1238 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1239 return Status;\r
1240 }\r
1241\r
1242 if (Tcp6State > Tcp6StateEstablished) {\r
1243 HttpCloseConnection (HttpInstance);\r
1244 }\r
1245\r
1246 return HttpCreateConnection (HttpInstance);\r
1247}\r
1248\r
1249/**\r
1250 Initialize TCP related data.\r
1251\r
1252 @param[in] HttpInstance The HTTP instance private data.\r
1253 @param[in] Wrap The HTTP token's wrap data.\r
1254\r
1255 @retval EFI_SUCCESS The initialization of TCP instance is done. \r
1256 @retval Others Other error as indicated.\r
1257\r
1258**/\r
1259EFI_STATUS\r
1260HttpInitTcp (\r
1261 IN HTTP_PROTOCOL *HttpInstance,\r
1262 IN HTTP_TOKEN_WRAP *Wrap\r
1263 )\r
1264{\r
1265 EFI_STATUS Status;\r
1266 ASSERT (HttpInstance != NULL);\r
1267\r
1268 if (!HttpInstance->LocalAddressIsIPv6) {\r
1269 //\r
1270 // Configure TCP instance.\r
1271 //\r
1272 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1273 if (EFI_ERROR (Status)) {\r
1274 return Status;\r
1275 }\r
1276 //\r
1277 // Connect TCP.\r
1278 //\r
1279 Status = HttpConnectTcp4 (HttpInstance);\r
1280 if (EFI_ERROR (Status)) {\r
1281 return Status;\r
1282 }\r
1283 } else {\r
1284 //\r
1285 // Configure TCP instance.\r
1286 //\r
1287 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1288 if (EFI_ERROR (Status)) {\r
1289 return Status;\r
1290 }\r
1291 //\r
1292 // Connect TCP.\r
1293 //\r
1294 Status = HttpConnectTcp6 (HttpInstance);\r
1295 if (EFI_ERROR (Status)) {\r
1296 return Status;\r
1297 }\r
1298 }\r
1299 \r
1300 return EFI_SUCCESS;\r
1301 \r
1302}\r
1303\r
1304/**\r
1305 Send the HTTP message through TCP4 or TCP6.\r
47f51a06
YT
1306\r
1307 @param[in] HttpInstance The HTTP instance private data.\r
1308 @param[in] Wrap The HTTP token's wrap data.\r
1309 @param[in] TxString Buffer containing the HTTP message string.\r
1310 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1311\r
1312 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1313 @retval Others Other error as indicated.\r
1314\r
1315**/\r
1316EFI_STATUS\r
b659408b 1317HttpTransmitTcp (\r
47f51a06
YT
1318 IN HTTP_PROTOCOL *HttpInstance,\r
1319 IN HTTP_TOKEN_WRAP *Wrap,\r
1320 IN UINT8 *TxString,\r
1321 IN UINTN TxStringLen\r
1322 )\r
1323{\r
1324 EFI_STATUS Status;\r
b659408b 1325 EFI_TCP4_IO_TOKEN *Tx4Token;\r
47f51a06 1326 EFI_TCP4_PROTOCOL *Tcp4;\r
b659408b
ZL
1327 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1328 EFI_TCP6_PROTOCOL *Tcp6;\r
47f51a06 1329 \r
b659408b
ZL
1330 if (!HttpInstance->LocalAddressIsIPv6) { \r
1331 Tcp4 = HttpInstance->Tcp4;\r
1332 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
1333 \r
1334 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1335 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1336 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1337 Tx4Token->CompletionToken.Status = EFI_NOT_READY; \r
1338 \r
1339 Wrap->TcpWrap.IsTxDone = FALSE;\r
1340 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1341 if (EFI_ERROR (Status)) {\r
1342 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1343 return Status;\r
1344 }\r
47f51a06 1345\r
b659408b
ZL
1346 } else {\r
1347 Tcp6 = HttpInstance->Tcp6;\r
1348 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
47f51a06 1349\r
b659408b
ZL
1350 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1351 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1352 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1353 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1354\r
1355 Wrap->TcpWrap.IsTxDone = FALSE;\r
1356 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1357 if (EFI_ERROR (Status)) {\r
1358 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1359 return Status;\r
1360 }\r
47f51a06 1361 }\r
b659408b 1362 \r
47f51a06
YT
1363\r
1364 return Status;\r
1365}\r
1366\r
1367/**\r
1368 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined \r
1369 in UEFI 2.5 specification.\r
1370\r
1371 @param[in] StatusCode The status code value in HTTP message.\r
1372\r
1373 @return Value defined in EFI_HTTP_STATUS_CODE .\r
1374\r
1375**/\r
1376EFI_HTTP_STATUS_CODE\r
1377HttpMappingToStatusCode (\r
1378 IN UINTN StatusCode\r
1379 ) \r
1380{\r
1381 switch (StatusCode) {\r
1382 case 100:\r
1383 return HTTP_STATUS_100_CONTINUE;\r
1384 case 101:\r
1385 return HTTP_STATUS_101_SWITCHING_PROTOCOLS;\r
1386 case 200:\r
1387 return HTTP_STATUS_200_OK;\r
1388 case 201:\r
1389 return HTTP_STATUS_201_CREATED;\r
1390 case 202:\r
1391 return HTTP_STATUS_202_ACCEPTED;\r
1392 case 203:\r
1393 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION;\r
1394 case 204:\r
1395 return HTTP_STATUS_204_NO_CONTENT;\r
1396 case 205:\r
1397 return HTTP_STATUS_205_RESET_CONTENT;\r
1398 case 206:\r
1399 return HTTP_STATUS_206_PARTIAL_CONTENT;\r
1400 case 300:\r
1401 return HTTP_STATUS_300_MULTIPLE_CHIOCES;\r
1402 case 301:\r
1403 return HTTP_STATUS_301_MOVED_PERMANENTLY;\r
1404 case 302:\r
1405 return HTTP_STATUS_302_FOUND;\r
1406 case 303:\r
1407 return HTTP_STATUS_303_SEE_OTHER;\r
1408 case 304:\r
1409 return HTTP_STATUS_304_NOT_MODIFIED;\r
1410 case 305:\r
1411 return HTTP_STATUS_305_USE_PROXY;\r
1412 case 307:\r
1413 return HTTP_STATUS_307_TEMPORARY_REDIRECT;\r
1414 case 400:\r
1415 return HTTP_STATUS_400_BAD_REQUEST;\r
1416 case 401:\r
1417 return HTTP_STATUS_401_UNAUTHORIZED;\r
1418 case 402:\r
1419 return HTTP_STATUS_402_PAYMENT_REQUIRED;\r
1420 case 403:\r
1421 return HTTP_STATUS_403_FORBIDDEN;\r
1422 case 404:\r
1423 return HTTP_STATUS_404_NOT_FOUND;\r
1424 case 405:\r
1425 return HTTP_STATUS_405_METHOD_NOT_ALLOWED;\r
1426 case 406:\r
1427 return HTTP_STATUS_406_NOT_ACCEPTABLE;\r
1428 case 407:\r
1429 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED;\r
1430 case 408:\r
1431 return HTTP_STATUS_408_REQUEST_TIME_OUT;\r
1432 case 409:\r
1433 return HTTP_STATUS_409_CONFLICT;\r
1434 case 410:\r
1435 return HTTP_STATUS_410_GONE;\r
1436 case 411:\r
1437 return HTTP_STATUS_411_LENGTH_REQUIRED;\r
1438 case 412:\r
1439 return HTTP_STATUS_412_PRECONDITION_FAILED;\r
1440 case 413:\r
1441 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE;\r
1442 case 414:\r
1443 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE;\r
1444 case 415:\r
8cfd008e 1445 return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE;\r
47f51a06
YT
1446 case 416:\r
1447 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED;\r
1448 case 417:\r
1449 return HTTP_STATUS_417_EXPECTATION_FAILED;\r
1450 case 500:\r
1451 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR;\r
1452 case 501:\r
8cfd008e 1453 return HTTP_STATUS_501_NOT_IMPLEMENTED;\r
47f51a06
YT
1454 case 502:\r
1455 return HTTP_STATUS_502_BAD_GATEWAY;\r
1456 case 503:\r
1457 return HTTP_STATUS_503_SERVICE_UNAVAILABLE;\r
1458 case 504:\r
1459 return HTTP_STATUS_504_GATEWAY_TIME_OUT;\r
1460 case 505:\r
1461 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED;\r
1462\r
1463 default:\r
1464 return HTTP_STATUS_UNSUPPORTED_STATUS;\r
1465 }\r
1466}\r
1467\r
1468/**\r
1469 Check whether the user's token or event has already\r
b659408b 1470 been enqueue on HTTP Tx or Rx Token list.\r
47f51a06
YT
1471\r
1472 @param[in] Map The container of either user's transmit or receive\r
1473 token.\r
1474 @param[in] Item Current item to check against.\r
1475 @param[in] Context The Token to check againist.\r
1476\r
1477 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1478 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1479 context.\r
1480\r
1481**/\r
1482EFI_STATUS\r
1483EFIAPI\r
1484HttpTokenExist (\r
1485 IN NET_MAP *Map,\r
1486 IN NET_MAP_ITEM *Item,\r
1487 IN VOID *Context\r
1488 )\r
1489{\r
1490 EFI_HTTP_TOKEN *Token;\r
1491 EFI_HTTP_TOKEN *TokenInItem;\r
1492\r
1493 Token = (EFI_HTTP_TOKEN *) Context;\r
1494 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1495\r
1496 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
1497 return EFI_ACCESS_DENIED;\r
1498 }\r
1499\r
1500 return EFI_SUCCESS;\r
1501}\r
1502\r
1503/**\r
b659408b 1504 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
47f51a06 1505\r
b659408b 1506 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1507 @param[in] Item Current item to check against.\r
1508 @param[in] Context The Token to check againist.\r
1509\r
1510 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1511 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1512\r
1513**/\r
1514EFI_STATUS\r
1515EFIAPI\r
1516HttpTcpNotReady (\r
1517 IN NET_MAP *Map,\r
1518 IN NET_MAP_ITEM *Item,\r
1519 IN VOID *Context\r
1520 )\r
1521{\r
1522 HTTP_TOKEN_WRAP *ValueInItem;\r
1523\r
1524 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1525\r
1526 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1527 return EFI_NOT_READY;\r
1528 }\r
1529 \r
1530 return EFI_SUCCESS;\r
1531}\r
1532\r
1533/**\r
1534 Transmit the HTTP mssage by processing the associated HTTP token.\r
1535\r
b659408b 1536 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1537 @param[in] Item Current item to check against.\r
1538 @param[in] Context The Token to check againist.\r
1539\r
1540 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1541 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1542 queue.\r
1543\r
1544**/\r
1545EFI_STATUS\r
1546EFIAPI\r
1547HttpTcpTransmit (\r
1548 IN NET_MAP *Map,\r
1549 IN NET_MAP_ITEM *Item,\r
1550 IN VOID *Context\r
1551 )\r
1552{\r
1553 HTTP_TOKEN_WRAP *ValueInItem;\r
1554 EFI_STATUS Status;\r
1555 CHAR8 *RequestStr;\r
1556 CHAR8 *Url;\r
1557\r
1558 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1559 if (ValueInItem->TcpWrap.IsTxDone) {\r
1560 return EFI_SUCCESS;\r
1561 }\r
1562\r
1563 //\r
1564 // Parse the URI of the remote host.\r
1565 //\r
1566 Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);\r
1567 if (Url == NULL) {\r
1568 return EFI_OUT_OF_RESOURCES;\r
1569 }\r
1570\r
1571 UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);\r
1572\r
1573 //\r
1574 // Create request message.\r
1575 //\r
1576 RequestStr = HttpGenRequestString (\r
1577 ValueInItem->HttpInstance,\r
1578 ValueInItem->HttpToken->Message,\r
1579 Url\r
1580 );\r
1581 FreePool (Url);\r
1582 if (RequestStr == NULL) {\r
1583 return EFI_OUT_OF_RESOURCES;\r
1584 }\r
1585\r
1586 //\r
1587 // Transmit the request message.\r
1588 //\r
b659408b 1589 Status = HttpTransmitTcp (\r
47f51a06
YT
1590 ValueInItem->HttpInstance,\r
1591 ValueInItem,\r
1592 (UINT8*) RequestStr,\r
1593 AsciiStrLen (RequestStr)\r
1594 );\r
1595 FreePool (RequestStr);\r
1596 return Status;\r
1597}\r
1598\r
1599/**\r
1600 Receive the HTTP response by processing the associated HTTP token.\r
1601\r
b659408b 1602 @param[in] Map The container of Rx4Token or Rx6Token.\r
47f51a06
YT
1603 @param[in] Item Current item to check against.\r
1604 @param[in] Context The Token to check againist.\r
1605\r
1606 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1607 queue.\r
1608 @retval Others Other error as indicated.\r
1609\r
1610**/\r
1611EFI_STATUS\r
1612EFIAPI\r
1613HttpTcpReceive (\r
1614 IN NET_MAP *Map,\r
1615 IN NET_MAP_ITEM *Item,\r
1616 IN VOID *Context\r
1617 )\r
1618{\r
1619 //\r
1620 // Process the queued HTTP response.\r
1621 //\r
1622 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1623}\r
1624\r
b659408b
ZL
1625/**\r
1626 Receive the HTTP header by processing the associated HTTP token.\r
1627\r
1628 @param[in] HttpInstance The HTTP instance private data.\r
1629 @param[in, out] SizeofHeaders The HTTP header length.\r
1630 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
1631 \r
1632 @retval EFI_SUCCESS The HTTP header is received. \r
1633 @retval Others Other errors as indicated.\r
1634\r
1635**/\r
1636EFI_STATUS\r
1637HttpTcpReceiveHeader (\r
1638 IN HTTP_PROTOCOL *HttpInstance,\r
1639 IN OUT UINTN *SizeofHeaders,\r
1640 IN OUT UINTN *BufferSize\r
1641 )\r
1642{\r
1643 EFI_STATUS Status;\r
1644 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1645 EFI_TCP4_PROTOCOL *Tcp4;\r
1646 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1647 EFI_TCP6_PROTOCOL *Tcp6;\r
1648 CHAR8 **EndofHeader;\r
1649 CHAR8 **HttpHeaders;\r
1650 CHAR8 *Buffer;\r
1651\r
1652 ASSERT (HttpInstance != NULL);\r
1653\r
1654 EndofHeader = HttpInstance->EndofHeader;\r
1655 HttpHeaders = HttpInstance->HttpHeaders;\r
1656 Tcp4 = HttpInstance->Tcp4;\r
1657 Tcp6 = HttpInstance->Tcp6;\r
1658 Buffer = NULL;\r
1659 Rx4Token = NULL;\r
1660 Rx6Token = NULL;\r
1661 \r
1662 if (HttpInstance->LocalAddressIsIPv6) {\r
1663 ASSERT (Tcp6 != NULL);\r
1664 } else {\r
1665 ASSERT (Tcp4 != NULL);\r
1666 }\r
1667\r
1668 if (!HttpInstance->LocalAddressIsIPv6) {\r
1669 Rx4Token = &HttpInstance->Rx4Token;\r
1670 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1671 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1672 Status = EFI_OUT_OF_RESOURCES;\r
1673 return Status;\r
1674 }\r
1675 \r
1676 //\r
1677 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1678 //\r
1679 while (*EndofHeader == NULL) { \r
1680 HttpInstance->IsRxDone = FALSE;\r
1681 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1682 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1683 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1684 if (EFI_ERROR (Status)) {\r
1685 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1686 return Status;\r
1687 }\r
1688 \r
1689 while (!HttpInstance->IsRxDone) {\r
1690 Tcp4->Poll (Tcp4);\r
1691 } \r
1692 \r
1693 Status = Rx4Token->CompletionToken.Status;\r
1694 if (EFI_ERROR (Status)) {\r
1695 return Status;\r
1696 }\r
1697 \r
1698 //\r
1699 // Append the response string.\r
1700 //\r
1701 *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1702 Buffer = AllocateZeroPool (*BufferSize);\r
1703 if (Buffer == NULL) {\r
1704 Status = EFI_OUT_OF_RESOURCES;\r
1705 return Status;\r
1706 }\r
1707 \r
1708 if (*HttpHeaders != NULL) {\r
1709 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1710 FreePool (*HttpHeaders);\r
1711 }\r
1712 \r
1713 CopyMem (\r
1714 Buffer + (*SizeofHeaders),\r
1715 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1716 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1717 );\r
1718 *HttpHeaders = Buffer;\r
1719 *SizeofHeaders = *BufferSize;\r
1720 \r
1721 //\r
1722 // Check whether we received end of HTTP headers.\r
1723 //\r
1724 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); \r
1725 }\r
1726 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1727 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1728 \r
1729 } else {\r
1730 Rx6Token = &HttpInstance->Rx6Token;\r
1731 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1732 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1733 Status = EFI_OUT_OF_RESOURCES;\r
1734 return Status;\r
1735 }\r
1736 \r
1737 //\r
1738 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1739 //\r
1740 while (*EndofHeader == NULL) { \r
1741 HttpInstance->IsRxDone = FALSE;\r
1742 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1743 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1744 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1745 if (EFI_ERROR (Status)) {\r
1746 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1747 return Status;\r
1748 }\r
1749 \r
1750 while (!HttpInstance->IsRxDone) {\r
1751 Tcp6->Poll (Tcp6);\r
1752 } \r
1753 \r
1754 Status = Rx6Token->CompletionToken.Status;\r
1755 if (EFI_ERROR (Status)) {\r
1756 return Status;\r
1757 }\r
1758 \r
1759 //\r
1760 // Append the response string.\r
1761 //\r
1762 *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1763 Buffer = AllocateZeroPool (*BufferSize);\r
1764 if (Buffer == NULL) {\r
1765 Status = EFI_OUT_OF_RESOURCES;\r
1766 return Status;\r
1767 }\r
1768 \r
1769 if (*HttpHeaders != NULL) {\r
1770 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1771 FreePool (*HttpHeaders);\r
1772 }\r
1773 \r
1774 CopyMem (\r
1775 Buffer + (*SizeofHeaders),\r
1776 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1777 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1778 );\r
1779 *HttpHeaders = Buffer;\r
1780 *SizeofHeaders = *BufferSize;\r
1781 \r
1782 //\r
1783 // Check whether we received end of HTTP headers.\r
1784 //\r
1785 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1786 \r
1787 }\r
1788 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1789 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; \r
1790 } \r
1791\r
1792 //\r
1793 // Skip the CRLF after the HTTP headers.\r
1794 //\r
1795 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); \r
1796\r
1797 return EFI_SUCCESS;\r
1798}\r
1799\r
1800/**\r
1801 Receive the HTTP body by processing the associated HTTP token.\r
1802\r
1803 @param[in] Wrap The HTTP token's wrap data.\r
1804 @param[in] HttpMsg The HTTP message data.\r
1805\r
1806 @retval EFI_SUCCESS The HTTP body is received. \r
1807 @retval Others Other error as indicated.\r
1808\r
1809**/\r
1810EFI_STATUS\r
1811HttpTcpReceiveBody (\r
1812 IN HTTP_TOKEN_WRAP *Wrap,\r
1813 IN EFI_HTTP_MESSAGE *HttpMsg\r
1814 )\r
1815{\r
1816 EFI_STATUS Status;\r
1817 HTTP_PROTOCOL *HttpInstance;\r
1818 EFI_TCP6_PROTOCOL *Tcp6;\r
1819 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1820 EFI_TCP4_PROTOCOL *Tcp4;\r
1821 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1822 \r
1823 HttpInstance = Wrap->HttpInstance;\r
1824 Tcp4 = HttpInstance->Tcp4;\r
1825 Tcp6 = HttpInstance->Tcp6;\r
1826 Rx4Token = NULL;\r
1827 Rx6Token = NULL;\r
1828\r
1829 \r
1830 if (HttpInstance->LocalAddressIsIPv6) {\r
1831 ASSERT (Tcp6 != NULL);\r
1832 } else {\r
1833 ASSERT (Tcp4 != NULL);\r
1834 }\r
1835 \r
1836 if (HttpInstance->LocalAddressIsIPv6) {\r
1837 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1838 Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1839 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1840 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1841 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1842\r
1843 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1844 if (EFI_ERROR (Status)) {\r
1845 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1846 return Status;\r
1847 }\r
1848 \r
1849 } else {\r
1850 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1851 Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1852 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1853 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1854 \r
1855 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1856 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1857 if (EFI_ERROR (Status)) {\r
1858 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1859 return Status;\r
1860 }\r
1861 }\r
1862\r
1863 return EFI_SUCCESS;\r
1864\r
1865}\r
1866\r
1867/**\r
1868 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
1869\r
1870 @param[in] Wrap Pointer to HTTP token's wrap data.\r
1871 \r
1872**/\r
1873VOID\r
1874HttpTcpTokenCleanup (\r
1875 IN HTTP_TOKEN_WRAP *Wrap\r
1876 )\r
1877{ \r
1878 HTTP_PROTOCOL *HttpInstance;\r
1879 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1880 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1881\r
1882 HttpInstance = Wrap->HttpInstance;\r
1883 Rx4Token = NULL;\r
1884 Rx6Token = NULL;\r
1885 \r
1886 if (HttpInstance->LocalAddressIsIPv6) {\r
1887 if (Wrap != NULL) {\r
1888 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
1889 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
1890 }\r
1891\r
1892 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1893 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1894 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1895 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1896 }\r
1897 FreePool (Wrap); \r
1898 }\r
1899\r
1900 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
1901 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
1902 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
1903 }\r
1904\r
1905 Rx6Token = &HttpInstance->Rx6Token;\r
1906 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1907 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1908 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1909 }\r
1910 \r
1911 } else {\r
1912 if (Wrap != NULL) {\r
1913 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
1914 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
1915 }\r
1916 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1917 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1918 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1919 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1920 }\r
1921 FreePool (Wrap);\r
1922 }\r
1923 \r
1924 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
1925 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
1926 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
1927 }\r
1928 \r
1929 Rx4Token = &HttpInstance->Rx4Token;\r
1930 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1931 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1932 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1933 }\r
1934 }\r
1935\r
1936}\r
1937\r
47f51a06
YT
1938/**\r
1939 Generate HTTP request string.\r
1940\r
1941 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
1942 @param[in] Message Pointer to storage containing HTTP message data.\r
1943 @param[in] Url The URL of a remote host.\r
1944\r
1945 @return Pointer to the created HTTP request string.\r
1946 @return NULL if any error occured.\r
1947\r
1948**/\r
1949CHAR8 *\r
1950HttpGenRequestString (\r
1951 IN HTTP_PROTOCOL *HttpInstance,\r
1952 IN EFI_HTTP_MESSAGE *Message,\r
1953 IN CHAR8 *Url\r
1954 )\r
1955{\r
1956 EFI_STATUS Status;\r
1957 UINTN StrLength;\r
1958 UINT8 *Request;\r
1959 UINT8 *RequestPtr;\r
1960 UINTN HttpHdrSize;\r
1961 UINTN MsgSize;\r
1962 BOOLEAN Success;\r
1963 VOID *HttpHdr;\r
1964 EFI_HTTP_HEADER **AppendList; \r
1965 UINTN Index;\r
1966 \r
1967 ASSERT (HttpInstance != NULL);\r
1968 ASSERT (Message != NULL);\r
1969\r
1970 DEBUG ((EFI_D_ERROR, "HttpMethod - %x\n", Message->Data.Request->Method));\r
1971\r
1972 Request = NULL;\r
1973 Success = FALSE;\r
1974 HttpHdr = NULL;\r
1975 AppendList = NULL;\r
1976\r
1977 //\r
1978 // Build AppendList\r
1979 //\r
1980 AppendList = AllocateZeroPool (sizeof (EFI_HTTP_HEADER *) * (Message->HeaderCount));\r
1981 if (AppendList == NULL) {\r
1982 return NULL;\r
1983 }\r
1984\r
1985 for(Index = 0; Index < Message->HeaderCount; Index++){\r
1986 AppendList[Index] = &Message->Headers[Index];\r
1987 }\r
1988\r
5ca29abe
JW
1989 //\r
1990 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.\r
1991 //\r
1992 if (mHttpUtilities == NULL) {\r
1993 return NULL;\r
1994 }\r
1995\r
47f51a06
YT
1996 //\r
1997 // Build raw unformatted HTTP headers.\r
5ca29abe
JW
1998 //\r
1999 Status = mHttpUtilities->Build (\r
2000 mHttpUtilities,\r
2001 0,\r
2002 NULL,\r
2003 0,\r
2004 NULL,\r
2005 Message->HeaderCount,\r
2006 AppendList,\r
2007 &HttpHdrSize,\r
2008 &HttpHdr\r
2009 );\r
47f51a06
YT
2010 FreePool (AppendList);\r
2011 if (EFI_ERROR (Status) || HttpHdr == NULL) {\r
2012 return NULL;\r
2013 }\r
2014\r
2015 //\r
2016 // Calculate HTTP message length.\r
2017 //\r
2018 MsgSize = Message->BodyLength + HTTP_MAXIMUM_METHOD_LEN + AsciiStrLen (Url) + \r
2019 AsciiStrLen (HTTP_VERSION_CRLF_STR) + HttpHdrSize;\r
2020 Request = AllocateZeroPool (MsgSize);\r
2021 if (Request == NULL) {\r
2022 goto Exit;\r
2023 } \r
2024\r
2025 RequestPtr = Request;\r
2026 //\r
2027 // Construct header request\r
2028 //\r
2029 switch (Message->Data.Request->Method) {\r
2030 case HttpMethodGet:\r
2031 StrLength = sizeof (HTTP_GET_STR) - 1;\r
2032 CopyMem (RequestPtr, HTTP_GET_STR, StrLength);\r
2033 RequestPtr += StrLength;\r
2034 break;\r
2035 case HttpMethodHead:\r
2036 StrLength = sizeof (HTTP_HEAD_STR) - 1;\r
2037 CopyMem (RequestPtr, HTTP_HEAD_STR, StrLength);\r
2038 RequestPtr += StrLength;\r
2039 break;\r
2040 default:\r
2041 ASSERT (FALSE);\r
2042 goto Exit;\r
2043 }\r
2044\r
2045 StrLength = AsciiStrLen (Url);\r
2046 CopyMem (RequestPtr, Url, StrLength);\r
2047 RequestPtr += StrLength;\r
2048\r
2049 StrLength = sizeof (HTTP_VERSION_CRLF_STR) - 1;\r
2050 CopyMem (RequestPtr, HTTP_VERSION_CRLF_STR, StrLength);\r
2051 RequestPtr += StrLength;\r
2052\r
2053 //\r
2054 // Construct header\r
2055 //\r
2056 CopyMem (RequestPtr, HttpHdr, HttpHdrSize);\r
2057 RequestPtr += HttpHdrSize;\r
2058\r
2059 //\r
2060 // Construct body\r
2061 //\r
2062 if (Message->Body != NULL) {\r
2063 CopyMem (RequestPtr, Message->Body, Message->BodyLength);\r
2064 RequestPtr += Message->BodyLength;\r
2065 }\r
2066\r
2067 //\r
2068 // Done\r
2069 //\r
2070 *RequestPtr = 0;\r
2071 Success = TRUE;\r
2072 \r
2073Exit:\r
2074\r
2075 if (!Success) {\r
2076 if (Request != NULL) {\r
2077 FreePool (Request);\r
2078 }\r
2079\r
2080 Request = NULL;\r
2081 }\r
2082\r
2083 if (HttpHdr != NULL) {\r
2084 FreePool (HttpHdr);\r
2085 }\r
2086\r
2087 return (CHAR8*) Request;\r
2088}\r