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