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