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