]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
MdeModulePkg: Fix incorrect status check for SockProcessRcvToken
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / SockInterface.c
CommitLineData
8a67d61d 1/** @file\r
dab714aa 2 Interface function of the Socket.\r
8a67d61d 3\r
5679a62a 4Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
8a67d61d 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
dfc1f033 8http://opensource.org/licenses/bsd-license.php<BR>\r
8a67d61d 9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
8a67d61d 13**/\r
14\r
15\r
16#include "SockImpl.h"\r
17\r
18\r
19/**\r
20 Check whether the Event is in the List.\r
21\r
22 @param List Pointer to the token list to be searched.\r
23 @param Event The event to be checked.\r
24\r
120db52c 25 @retval TRUE The specific Event exists in the List. \r
77f00155 26 @retval FALSE The specific Event is not in the List.\r
8a67d61d 27\r
28**/\r
8a67d61d 29BOOLEAN\r
30SockTokenExistedInList (\r
e48e37fc 31 IN LIST_ENTRY *List,\r
8a67d61d 32 IN EFI_EVENT Event\r
33 )\r
34{\r
e48e37fc 35 LIST_ENTRY *ListEntry;\r
8a67d61d 36 SOCK_TOKEN *SockToken;\r
37\r
38 NET_LIST_FOR_EACH (ListEntry, List) {\r
39 SockToken = NET_LIST_USER_STRUCT (\r
40 ListEntry,\r
41 SOCK_TOKEN,\r
42 TokenList\r
43 );\r
44\r
45 if (Event == SockToken->Token->Event) {\r
46 return TRUE;\r
47 }\r
48 }\r
49\r
50 return FALSE;\r
51}\r
52\r
53\r
54/**\r
55 Call SockTokenExistedInList() to check whether the Event is\r
56 in the related socket's lists.\r
57\r
58 @param Sock Pointer to the instance's socket.\r
59 @param Event The event to be checked.\r
60\r
77f00155 61 @retval TRUE The Event exists in related socket's lists. \r
62 @retval FALSE The Event is not in related socket's lists.\r
8a67d61d 63\r
64**/\r
65BOOLEAN\r
66SockTokenExisted (\r
67 IN SOCKET *Sock,\r
68 IN EFI_EVENT Event\r
69 )\r
70{\r
71\r
72 if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||\r
73 SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||\r
74 SockTokenExistedInList (&Sock->RcvTokenList, Event) ||\r
120db52c 75 SockTokenExistedInList (&Sock->ListenTokenList, Event)) {\r
8a67d61d 76\r
77 return TRUE;\r
78 }\r
79\r
80 if ((Sock->ConnectionToken != NULL) &&\r
81 (Sock->ConnectionToken->Event == Event)) {\r
82\r
83 return TRUE;\r
84 }\r
85\r
86 if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {\r
87 return TRUE;\r
88 }\r
89\r
90 return FALSE;\r
91}\r
92\r
93\r
94/**\r
95 Buffer a token into the specific list of socket Sock.\r
96\r
97 @param Sock Pointer to the instance's socket.\r
98 @param List Pointer to the list to store the token.\r
99 @param Token Pointer to the token to be buffered.\r
100 @param DataLen The data length of the buffer contained in Token.\r
101\r
102 @return Pointer to the token that wraps Token. If NULL, error condition occurred.\r
103\r
104**/\r
105SOCK_TOKEN *\r
106SockBufferToken (\r
107 IN SOCKET *Sock,\r
e48e37fc 108 IN LIST_ENTRY *List,\r
8a67d61d 109 IN VOID *Token,\r
110 IN UINT32 DataLen\r
111 )\r
112{\r
113 SOCK_TOKEN *SockToken;\r
114\r
e48e37fc 115 SockToken = AllocatePool (sizeof (SOCK_TOKEN));\r
8a67d61d 116 if (NULL == SockToken) {\r
117\r
e48e37fc 118 DEBUG ((EFI_D_ERROR, "SockBufferIOToken: No Memory "\r
8a67d61d 119 "to allocate SockToken\n"));\r
120\r
121 return NULL;\r
122 }\r
123\r
124 SockToken->Sock = Sock;\r
125 SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;\r
126 SockToken->RemainDataLen = DataLen;\r
e48e37fc 127 InsertTailList (List, &SockToken->TokenList);\r
8a67d61d 128\r
129 return SockToken;\r
130}\r
131\r
132\r
133/**\r
75dce340 134 Destroy the socket Sock and its associated protocol control block.\r
8a67d61d 135\r
136 @param Sock The socket to be destroyed.\r
137\r
138 @retval EFI_SUCCESS The socket Sock is destroyed successfully.\r
139 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
140\r
141**/\r
142EFI_STATUS\r
143SockDestroyChild (\r
77f00155 144 IN SOCKET *Sock\r
8a67d61d 145 )\r
146{\r
147 EFI_STATUS Status;\r
148\r
120db52c 149 ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));\r
8a67d61d 150\r
216f7970 151 if (Sock->InDestroy) {\r
8a67d61d 152 return EFI_SUCCESS;\r
153 }\r
154\r
216f7970 155 Sock->InDestroy = TRUE;\r
8a67d61d 156\r
e48e37fc 157 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 158 if (EFI_ERROR (Status)) {\r
159\r
e48e37fc 160 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Get the lock to "\r
8a67d61d 161 "access socket failed with %r\n", Status));\r
162\r
163 return EFI_ACCESS_DENIED;\r
164 }\r
165\r
166 //\r
167 // force protocol layer to detach the PCB\r
168 //\r
169 Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);\r
170\r
171 if (EFI_ERROR (Status)) {\r
172\r
e48e37fc 173 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Protocol detach socket"\r
8a67d61d 174 " failed with %r\n", Status));\r
175\r
216f7970 176 Sock->InDestroy = FALSE;\r
8a67d61d 177 } else if (SOCK_IS_CONFIGURED (Sock)) {\r
178\r
179 SockConnFlush (Sock);\r
180 SockSetState (Sock, SO_CLOSED);\r
181\r
182 Sock->ConfigureState = SO_UNCONFIGURED;\r
183 }\r
184\r
e48e37fc 185 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 186\r
187 if (EFI_ERROR (Status)) {\r
188 return Status;\r
189 }\r
190\r
191 SockDestroy (Sock);\r
192 return EFI_SUCCESS;\r
193}\r
194\r
195\r
196/**\r
197 Create a socket and its associated protocol control block\r
198 with the intial data SockInitData and protocol specific\r
199 data ProtoData.\r
200\r
201 @param SockInitData Inital data to setting the socket.\r
85511ddf 202 \r
8a67d61d 203 @return Pointer to the newly created socket. If NULL, error condition occured.\r
204\r
205**/\r
206SOCKET *\r
207SockCreateChild (\r
4f6e31e4 208 IN SOCK_INIT_DATA *SockInitData\r
8a67d61d 209 )\r
210{\r
211 SOCKET *Sock;\r
212 EFI_STATUS Status;\r
213\r
8a67d61d 214 //\r
215 // create a new socket\r
216 //\r
217 Sock = SockCreate (SockInitData);\r
218 if (NULL == Sock) {\r
219\r
e48e37fc 220 DEBUG ((EFI_D_ERROR, "SockCreateChild: No resource to "\r
8a67d61d 221 "create a new socket\n"));\r
222\r
223 return NULL;\r
224 }\r
225\r
e48e37fc 226 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 227 if (EFI_ERROR (Status)) {\r
228\r
e48e37fc 229 DEBUG ((EFI_D_ERROR, "SockCreateChild: Get the lock to "\r
8a67d61d 230 "access socket failed with %r\n", Status));\r
231\r
232 SockDestroy (Sock);\r
233 return NULL;\r
234 }\r
235 //\r
236 // inform the protocol layer to attach the socket\r
237 // with a new protocol control block\r
238 //\r
239 Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);\r
54ea3ede 240 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 241 if (EFI_ERROR (Status)) {\r
242\r
e48e37fc 243 DEBUG ((EFI_D_ERROR, "SockCreateChild: Protocol failed to"\r
8a67d61d 244 " attach a socket with %r\n", Status));\r
245\r
246 SockDestroy (Sock);\r
247 Sock = NULL;\r
248 }\r
249\r
8a67d61d 250 return Sock;\r
251}\r
252\r
253\r
254/**\r
120db52c 255 Configure the specific socket Sock using configuration data ConfigData.\r
8a67d61d 256\r
257 @param Sock Pointer to the socket to be configured.\r
258 @param ConfigData Pointer to the configuration data.\r
259\r
260 @retval EFI_SUCCESS The socket is configured successfully.\r
261 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the\r
262 socket is already configured.\r
263\r
264**/\r
265EFI_STATUS\r
266SockConfigure (\r
267 IN SOCKET *Sock,\r
268 IN VOID *ConfigData\r
269 )\r
270{\r
271 EFI_STATUS Status;\r
272\r
e48e37fc 273 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 274 if (EFI_ERROR (Status)) {\r
275\r
e48e37fc 276 DEBUG ((EFI_D_ERROR, "SockConfigure: Get the access for "\r
8a67d61d 277 "socket failed with %r", Status));\r
278\r
279 return EFI_ACCESS_DENIED;\r
280 }\r
281\r
282 if (SOCK_IS_CONFIGURED (Sock)) {\r
283 Status = EFI_ACCESS_DENIED;\r
284 goto OnExit;\r
285 }\r
286\r
287 ASSERT (Sock->State == SO_CLOSED);\r
288\r
289 Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);\r
290\r
291OnExit:\r
e48e37fc 292 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 293\r
294 return Status;\r
295}\r
296\r
297\r
298/**\r
299 Initiate a connection establishment process.\r
300\r
301 @param Sock Pointer to the socket to initiate the initate the\r
302 connection.\r
303 @param Token Pointer to the token used for the connection\r
304 operation.\r
305\r
306 @retval EFI_SUCCESS The connection is initialized successfully.\r
307 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
308 socket is closed, or the socket is not configured to\r
309 be an active one, or the token is already in one of\r
310 this socket's lists.\r
311 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
312 finished.\r
313 @retval EFI_NOT_STARTED The socket is not configured.\r
314\r
315**/\r
316EFI_STATUS\r
317SockConnect (\r
318 IN SOCKET *Sock,\r
319 IN VOID *Token\r
320 )\r
321{\r
322 EFI_STATUS Status;\r
323 EFI_EVENT Event;\r
324\r
e48e37fc 325 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 326 if (EFI_ERROR (Status)) {\r
327\r
e48e37fc 328 DEBUG ((EFI_D_ERROR, "SockConnect: Get the access for "\r
8a67d61d 329 "socket failed with %r", Status));\r
330\r
331 return EFI_ACCESS_DENIED;\r
332 }\r
333\r
334 if (SOCK_IS_NO_MAPPING (Sock)) {\r
335 Status = EFI_NO_MAPPING;\r
336 goto OnExit;\r
337 }\r
338\r
339 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
340\r
341 Status = EFI_NOT_STARTED;\r
342 goto OnExit;\r
343 }\r
344\r
345 if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {\r
346\r
347 Status = EFI_ACCESS_DENIED;\r
348 goto OnExit;\r
349 }\r
350\r
351 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
352\r
353 if (SockTokenExisted (Sock, Event)) {\r
354\r
355 Status = EFI_ACCESS_DENIED;\r
356 goto OnExit;\r
357 }\r
358\r
359 Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;\r
360 SockSetState (Sock, SO_CONNECTING);\r
361 Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);\r
362\r
363OnExit:\r
e48e37fc 364 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 365 return Status;\r
366}\r
367\r
368\r
369/**\r
370 Issue a listen token to get an existed connected network instance\r
371 or wait for a connection if there is none.\r
372\r
373 @param Sock Pointer to the socket to accept connections.\r
374 @param Token The token to accept a connection.\r
375\r
376 @retval EFI_SUCCESS Either a connection is accpeted or the Token is\r
377 buffered for further acception.\r
378 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
379 socket is closed, or the socket is not configured to\r
380 be a passive one, or the token is already in one of\r
381 this socket's lists.\r
382 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
383 finished.\r
384 @retval EFI_NOT_STARTED The socket is not configured.\r
385 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.\r
386\r
387**/\r
388EFI_STATUS\r
389SockAccept (\r
390 IN SOCKET *Sock,\r
391 IN VOID *Token\r
392 )\r
393{\r
394 EFI_TCP4_LISTEN_TOKEN *ListenToken;\r
e48e37fc 395 LIST_ENTRY *ListEntry;\r
8a67d61d 396 EFI_STATUS Status;\r
397 SOCKET *Socket;\r
398 EFI_EVENT Event;\r
399\r
f6b7393c 400 ASSERT (SockStream == Sock->Type);\r
8a67d61d 401\r
e48e37fc 402 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 403 if (EFI_ERROR (Status)) {\r
404\r
e48e37fc 405 DEBUG ((EFI_D_ERROR, "SockAccept: Get the access for socket"\r
8a67d61d 406 " failed with %r", Status));\r
407\r
408 return EFI_ACCESS_DENIED;\r
409 }\r
410\r
411 if (SOCK_IS_NO_MAPPING (Sock)) {\r
412 Status = EFI_NO_MAPPING;\r
413 goto Exit;\r
414 }\r
415\r
416 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
417\r
418 Status = EFI_NOT_STARTED;\r
419 goto Exit;\r
420 }\r
421\r
422 if (!SOCK_IS_LISTENING (Sock)) {\r
423\r
424 Status = EFI_ACCESS_DENIED;\r
425 goto Exit;\r
426 }\r
427\r
428 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
429\r
430 if (SockTokenExisted (Sock, Event)) {\r
431\r
432 Status = EFI_ACCESS_DENIED;\r
433 goto Exit;\r
434 }\r
435\r
436 ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;\r
437\r
438 //\r
439 // Check if a connection has already in this Sock->ConnectionList\r
440 //\r
441 NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {\r
442\r
443 Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);\r
444\r
445 if (SOCK_IS_CONNECTED (Socket)) {\r
446 ListenToken->NewChildHandle = Socket->SockHandle;\r
447 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);\r
448\r
e48e37fc 449 RemoveEntryList (ListEntry);\r
8a67d61d 450\r
120db52c 451 ASSERT (Socket->Parent != NULL);\r
8a67d61d 452\r
453 Socket->Parent->ConnCnt--;\r
454\r
e48e37fc 455 DEBUG (\r
dfc1f033 456 (EFI_D_INFO,\r
e48e37fc 457 "SockAccept: Accept a socket, now conncount is %d",\r
458 Socket->Parent->ConnCnt)\r
8a67d61d 459 );\r
460 Socket->Parent = NULL;\r
461\r
462 goto Exit;\r
463 }\r
464 }\r
465\r
466 //\r
467 // Buffer this token for latter incoming connection request\r
468 //\r
469 if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {\r
470\r
471 Status = EFI_OUT_OF_RESOURCES;\r
472 }\r
473\r
474Exit:\r
e48e37fc 475 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 476\r
477 return Status;\r
478}\r
479\r
480\r
481/**\r
482 Issue a token with data to the socket to send out.\r
483\r
484 @param Sock Pointer to the socket to process the token with\r
485 data.\r
486 @param Token The token with data that needs to send out.\r
487\r
488 @retval EFI_SUCCESS The token is processed successfully.\r
489 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
490 socket is closed, or the socket is not in a\r
491 synchronized state , or the token is already in one\r
492 of this socket's lists.\r
493 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
494 finished.\r
495 @retval EFI_NOT_STARTED The socket is not configured.\r
496 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
497\r
498**/\r
499EFI_STATUS\r
500SockSend (\r
501 IN SOCKET *Sock,\r
502 IN VOID *Token\r
503 )\r
504{\r
505 SOCK_IO_TOKEN *SndToken;\r
506 EFI_EVENT Event;\r
507 UINT32 FreeSpace;\r
508 EFI_TCP4_TRANSMIT_DATA *TxData;\r
509 EFI_STATUS Status;\r
510 SOCK_TOKEN *SockToken;\r
511 UINT32 DataLen;\r
512\r
f6b7393c 513 ASSERT (SockStream == Sock->Type);\r
8a67d61d 514\r
e48e37fc 515 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 516 if (EFI_ERROR (Status)) {\r
517\r
e48e37fc 518 DEBUG ((EFI_D_ERROR, "SockSend: Get the access for socket"\r
8a67d61d 519 " failed with %r", Status));\r
520\r
521 return EFI_ACCESS_DENIED;\r
522 }\r
523\r
524 if (SOCK_IS_NO_MAPPING (Sock)) {\r
525 Status = EFI_NO_MAPPING;\r
526 goto Exit;\r
527 }\r
528\r
529 SndToken = (SOCK_IO_TOKEN *) Token;\r
530 TxData = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;\r
531\r
532 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
533 Status = EFI_NOT_STARTED;\r
534 goto Exit;\r
535 }\r
536\r
537 if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {\r
538\r
539 Status = EFI_ACCESS_DENIED;\r
540 goto Exit;\r
541 }\r
542\r
543 //\r
544 // check if a token is already in the token buffer\r
545 //\r
546 Event = SndToken->Token.Event;\r
547\r
548 if (SockTokenExisted (Sock, Event)) {\r
549 Status = EFI_ACCESS_DENIED;\r
550 goto Exit;\r
551 }\r
552\r
4eb65aff 553 DataLen = (UINT32) TxData->DataLength;\r
8a67d61d 554\r
555 //\r
556 // process this sending token now or buffer it only?\r
557 //\r
558 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);\r
559\r
560 if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {\r
561\r
562 SockToken = SockBufferToken (\r
563 Sock,\r
564 &Sock->SndTokenList,\r
565 SndToken,\r
566 DataLen\r
567 );\r
568\r
569 if (NULL == SockToken) {\r
570 Status = EFI_OUT_OF_RESOURCES;\r
571 }\r
572 } else {\r
573\r
574 SockToken = SockBufferToken (\r
575 Sock,\r
576 &Sock->ProcessingSndTokenList,\r
577 SndToken,\r
578 DataLen\r
579 );\r
580\r
581 if (NULL == SockToken) {\r
e48e37fc 582 DEBUG ((EFI_D_ERROR, "SockSend: Failed to buffer IO token into"\r
8a67d61d 583 " socket processing SndToken List\n", Status));\r
584\r
585 Status = EFI_OUT_OF_RESOURCES;\r
586 goto Exit;\r
587 }\r
588\r
589 Status = SockProcessTcpSndData (Sock, TxData);\r
590\r
591 if (EFI_ERROR (Status)) {\r
e48e37fc 592 DEBUG ((EFI_D_ERROR, "SockSend: Failed to process "\r
8a67d61d 593 "Snd Data\n", Status));\r
594\r
e48e37fc 595 RemoveEntryList (&(SockToken->TokenList));\r
766c7483 596 FreePool (SockToken);\r
8a67d61d 597 }\r
598 }\r
599\r
600Exit:\r
e48e37fc 601 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 602 return Status;\r
603}\r
604\r
605\r
606/**\r
607 Issue a token to get data from the socket.\r
608\r
609 @param Sock Pointer to the socket to get data from.\r
610 @param Token The token to store the received data from the\r
611 socket.\r
612\r
613 @retval EFI_SUCCESS The token is processed successfully.\r
614 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
615 socket is closed, or the socket is not in a\r
616 synchronized state , or the token is already in one\r
617 of this socket's lists.\r
618 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
619 finished.\r
620 @retval EFI_NOT_STARTED The socket is not configured.\r
621 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.\r
622 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
623\r
624**/\r
625EFI_STATUS\r
626SockRcv (\r
627 IN SOCKET *Sock,\r
628 IN VOID *Token\r
629 )\r
630{\r
631 SOCK_IO_TOKEN *RcvToken;\r
632 UINT32 RcvdBytes;\r
633 EFI_STATUS Status;\r
634 EFI_EVENT Event;\r
635\r
f6b7393c 636 ASSERT (SockStream == Sock->Type);\r
8a67d61d 637\r
e48e37fc 638 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 639 if (EFI_ERROR (Status)) {\r
640\r
e48e37fc 641 DEBUG ((EFI_D_ERROR, "SockRcv: Get the access for socket"\r
8a67d61d 642 " failed with %r", Status));\r
643\r
644 return EFI_ACCESS_DENIED;\r
645 }\r
646\r
647 if (SOCK_IS_NO_MAPPING (Sock)) {\r
648\r
649 Status = EFI_NO_MAPPING;\r
650 goto Exit;\r
651 }\r
652\r
653 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
654\r
655 Status = EFI_NOT_STARTED;\r
656 goto Exit;\r
657 }\r
658\r
659 if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {\r
660\r
661 Status = EFI_ACCESS_DENIED;\r
662 goto Exit;\r
663 }\r
664\r
665 RcvToken = (SOCK_IO_TOKEN *) Token;\r
666\r
667 //\r
668 // check if a token is already in the token buffer of this socket\r
669 //\r
670 Event = RcvToken->Token.Event;\r
671 if (SockTokenExisted (Sock, Event)) {\r
672 Status = EFI_ACCESS_DENIED;\r
673 goto Exit;\r
674 }\r
675\r
676 RcvToken = (SOCK_IO_TOKEN *) Token;\r
677 RcvdBytes = GET_RCV_DATASIZE (Sock);\r
678\r
679 //\r
680 // check whether an error has happened before\r
681 //\r
682 if (EFI_ABORTED != Sock->SockError) {\r
683\r
684 SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);\r
685 Sock->SockError = EFI_ABORTED;\r
686 goto Exit;\r
687 }\r
688\r
689 //\r
690 // check whether can not receive and there is no any\r
691 // data buffered in Sock->RcvBuffer\r
692 //\r
693 if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {\r
694\r
695 Status = EFI_CONNECTION_FIN;\r
696 goto Exit;\r
697 }\r
698\r
699 if (RcvdBytes != 0) {\r
5679a62a 700 SockProcessRcvToken (Sock, RcvToken);\r
8a67d61d 701\r
702 Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);\r
703 } else {\r
704\r
705 if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {\r
706 Status = EFI_OUT_OF_RESOURCES;\r
707 }\r
708 }\r
709\r
710Exit:\r
e48e37fc 711 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 712 return Status;\r
713}\r
714\r
715\r
716/**\r
717 Reset the socket and its associated protocol control block.\r
718\r
719 @param Sock Pointer to the socket to be flushed.\r
720\r
721 @retval EFI_SUCCESS The socket is flushed successfully.\r
722 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
723\r
724**/\r
725EFI_STATUS\r
726SockFlush (\r
727 IN SOCKET *Sock\r
728 )\r
729{\r
730 EFI_STATUS Status;\r
731\r
f6b7393c 732 ASSERT (SockStream == Sock->Type);\r
8a67d61d 733\r
e48e37fc 734 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 735 if (EFI_ERROR (Status)) {\r
736\r
e48e37fc 737 DEBUG ((EFI_D_ERROR, "SockFlush: Get the access for socket"\r
8a67d61d 738 " failed with %r", Status));\r
739\r
740 return EFI_ACCESS_DENIED;\r
741 }\r
742\r
743 if (!SOCK_IS_CONFIGURED (Sock)) {\r
744 goto Exit;\r
745 }\r
746\r
747 Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);\r
748 if (EFI_ERROR (Status)) {\r
749\r
e48e37fc 750 DEBUG ((EFI_D_ERROR, "SockFlush: Protocol failed handling"\r
8a67d61d 751 " SOCK_FLUSH with %r", Status));\r
752\r
753 goto Exit;\r
754 }\r
755\r
756 SOCK_ERROR (Sock, EFI_ABORTED);\r
757 SockConnFlush (Sock);\r
758 SockSetState (Sock, SO_CLOSED);\r
759\r
760 Sock->ConfigureState = SO_UNCONFIGURED;\r
761\r
762Exit:\r
e48e37fc 763 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 764 return Status;\r
765}\r
766\r
767\r
768/**\r
769 Close or abort the socket associated connection.\r
770\r
771 @param Sock Pointer to the socket of the connection to close or\r
772 abort.\r
773 @param Token The token for close operation.\r
774 @param OnAbort TRUE for aborting the connection, FALSE to close it.\r
775\r
776 @retval EFI_SUCCESS The close or abort operation is initialized\r
777 successfully.\r
778 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
779 socket is closed, or the socket is not in a\r
780 synchronized state , or the token is already in one\r
781 of this socket's lists.\r
782 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
783 finished.\r
784 @retval EFI_NOT_STARTED The socket is not configured.\r
785\r
786**/\r
787EFI_STATUS\r
788SockClose (\r
789 IN SOCKET *Sock,\r
790 IN VOID *Token,\r
791 IN BOOLEAN OnAbort\r
792 )\r
793{\r
794 EFI_STATUS Status;\r
795 EFI_EVENT Event;\r
796\r
f6b7393c 797 ASSERT (SockStream == Sock->Type);\r
8a67d61d 798\r
e48e37fc 799 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 800 if (EFI_ERROR (Status)) {\r
e48e37fc 801 DEBUG ((EFI_D_ERROR, "SockClose: Get the access for socket"\r
8a67d61d 802 " failed with %r", Status));\r
803\r
804 return EFI_ACCESS_DENIED;\r
805 }\r
806\r
807 if (SOCK_IS_NO_MAPPING (Sock)) {\r
808 Status = EFI_NO_MAPPING;\r
809 goto Exit;\r
810 }\r
811\r
812 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
813 Status = EFI_NOT_STARTED;\r
814 goto Exit;\r
815 }\r
816\r
817 if (SOCK_IS_DISCONNECTING (Sock)) {\r
818 Status = EFI_ACCESS_DENIED;\r
819 goto Exit;\r
820 }\r
821\r
822 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
823\r
824 if (SockTokenExisted (Sock, Event)) {\r
825 Status = EFI_ACCESS_DENIED;\r
826 goto Exit;\r
827 }\r
828\r
829 Sock->CloseToken = Token;\r
830 SockSetState (Sock, SO_DISCONNECTING);\r
831\r
832 if (OnAbort) {\r
833 Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);\r
834 } else {\r
835 Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);\r
836 }\r
837\r
838Exit:\r
e48e37fc 839 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 840 return Status;\r
841}\r
842\r
843\r
844/**\r
845 Get the mode data of the low layer protocol.\r
846\r
847 @param Sock Pointer to the socket to get mode data from.\r
848 @param Mode Pointer to the data to store the low layer mode\r
849 information.\r
850\r
851 @retval EFI_SUCCESS The mode data is got successfully.\r
852 @retval EFI_NOT_STARTED The socket is not configured.\r
853\r
854**/\r
855EFI_STATUS\r
856SockGetMode (\r
276dcc1b 857 IN SOCKET *Sock,\r
858 IN OUT VOID *Mode\r
8a67d61d 859 )\r
860{\r
861 return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);\r
862}\r
863\r
864\r
865/**\r
866 Configure the low level protocol to join a multicast group for\r
867 this socket's connection.\r
868\r
869 @param Sock Pointer to the socket of the connection to join the\r
870 specific multicast group.\r
871 @param GroupInfo Pointer to the multicast group info.\r
872\r
873 @retval EFI_SUCCESS The configuration is done successfully.\r
874 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
875 @retval EFI_NOT_STARTED The socket is not configured.\r
876\r
877**/\r
878EFI_STATUS\r
879SockGroup (\r
880 IN SOCKET *Sock,\r
881 IN VOID *GroupInfo\r
882 )\r
883{\r
884 EFI_STATUS Status;\r
885\r
e48e37fc 886 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 887\r
888 if (EFI_ERROR (Status)) {\r
889\r
e48e37fc 890 DEBUG ((EFI_D_ERROR, "SockGroup: Get the access for socket"\r
8a67d61d 891 " failed with %r", Status));\r
892\r
893 return EFI_ACCESS_DENIED;\r
894 }\r
895\r
896 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
897 Status = EFI_NOT_STARTED;\r
898 goto Exit;\r
899 }\r
900\r
901 Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);\r
902\r
903Exit:\r
e48e37fc 904 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 905 return Status;\r
906}\r
907\r
908\r
909/**\r
910 Add or remove route information in IP route table associated\r
911 with this socket.\r
912\r
913 @param Sock Pointer to the socket associated with the IP route\r
914 table to operate on.\r
915 @param RouteInfo Pointer to the route information to be processed.\r
916\r
917 @retval EFI_SUCCESS The route table is updated successfully.\r
918 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
919 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
920 finished.\r
921 @retval EFI_NOT_STARTED The socket is not configured.\r
922\r
923**/\r
924EFI_STATUS\r
925SockRoute (\r
926 IN SOCKET *Sock,\r
927 IN VOID *RouteInfo\r
928 )\r
929{\r
930 EFI_STATUS Status;\r
931\r
e48e37fc 932 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 933 if (EFI_ERROR (Status)) {\r
e48e37fc 934 DEBUG ((EFI_D_ERROR, "SockRoute: Get the access for socket"\r
8a67d61d 935 " failed with %r", Status));\r
936\r
937 return EFI_ACCESS_DENIED;\r
938 }\r
939\r
940 if (SOCK_IS_NO_MAPPING (Sock)) {\r
941 Status = EFI_NO_MAPPING;\r
942 goto Exit;\r
943 }\r
944\r
945 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
946 Status = EFI_NOT_STARTED;\r
947 goto Exit;\r
948 }\r
949\r
950 Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);\r
951\r
952Exit:\r
e48e37fc 953 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 954 return Status;\r
955}\r