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