]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
Fix a missing doxygen parameter entry.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / SockInterface.c
... / ...
CommitLineData
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
31 @retval TRUE The specific Event exists in the List. \r
32 @retval False The specific Event is not in the List.\r
33\r
34**/\r
35BOOLEAN\r
36SockTokenExistedInList (\r
37 IN LIST_ENTRY *List,\r
38 IN EFI_EVENT Event\r
39 )\r
40{\r
41 LIST_ENTRY *ListEntry;\r
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
80 SockTokenExistedInList (&Sock->ListenTokenList, Event)) {\r
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
113 IN LIST_ENTRY *List,\r
114 IN VOID *Token,\r
115 IN UINT32 DataLen\r
116 )\r
117{\r
118 SOCK_TOKEN *SockToken;\r
119\r
120 SockToken = AllocatePool (sizeof (SOCK_TOKEN));\r
121 if (NULL == SockToken) {\r
122\r
123 DEBUG ((EFI_D_ERROR, "SockBufferIOToken: No Memory "\r
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
132 InsertTailList (List, &SockToken->TokenList);\r
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
154 ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));\r
155\r
156 if (Sock->IsDestroyed) {\r
157 return EFI_SUCCESS;\r
158 }\r
159\r
160 Sock->IsDestroyed = TRUE;\r
161\r
162 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
163 if (EFI_ERROR (Status)) {\r
164\r
165 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Get the lock to "\r
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
178 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Protocol detach socket"\r
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
190 EfiReleaseLock (&(Sock->Lock));\r
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
207 \r
208 @return Pointer to the newly created socket. If NULL, error condition occured.\r
209\r
210**/\r
211SOCKET *\r
212SockCreateChild (\r
213 IN SOCK_INIT_DATA *SockInitData\r
214 )\r
215{\r
216 SOCKET *Sock;\r
217 EFI_STATUS Status;\r
218\r
219 //\r
220 // create a new socket\r
221 //\r
222 Sock = SockCreate (SockInitData);\r
223 if (NULL == Sock) {\r
224\r
225 DEBUG ((EFI_D_ERROR, "SockCreateChild: No resource to "\r
226 "create a new socket\n"));\r
227\r
228 return NULL;\r
229 }\r
230\r
231 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
232 if (EFI_ERROR (Status)) {\r
233\r
234 DEBUG ((EFI_D_ERROR, "SockCreateChild: Get the lock to "\r
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
247 DEBUG ((EFI_D_ERROR, "SockCreateChild: Protocol failed to"\r
248 " attach a socket with %r\n", Status));\r
249\r
250 SockDestroy (Sock);\r
251 Sock = NULL;\r
252 }\r
253\r
254 EfiReleaseLock (&(Sock->Lock));\r
255 return Sock;\r
256}\r
257\r
258\r
259/**\r
260 Configure the specific socket Sock using configuration data ConfigData.\r
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
278 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
279 if (EFI_ERROR (Status)) {\r
280\r
281 DEBUG ((EFI_D_ERROR, "SockConfigure: Get the access for "\r
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
297 EfiReleaseLock (&(Sock->Lock));\r
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
330 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
331 if (EFI_ERROR (Status)) {\r
332\r
333 DEBUG ((EFI_D_ERROR, "SockConnect: Get the access for "\r
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
369 EfiReleaseLock (&(Sock->Lock));\r
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
400 LIST_ENTRY *ListEntry;\r
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
407 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
408 if (EFI_ERROR (Status)) {\r
409\r
410 DEBUG ((EFI_D_ERROR, "SockAccept: Get the access for socket"\r
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
454 RemoveEntryList (ListEntry);\r
455\r
456 ASSERT (Socket->Parent != NULL);\r
457\r
458 Socket->Parent->ConnCnt--;\r
459\r
460 DEBUG (\r
461 (EFI_D_WARN,\r
462 "SockAccept: Accept a socket, now conncount is %d",\r
463 Socket->Parent->ConnCnt)\r
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
480 EfiReleaseLock (&(Sock->Lock));\r
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
520 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
521 if (EFI_ERROR (Status)) {\r
522\r
523 DEBUG ((EFI_D_ERROR, "SockSend: Get the access for socket"\r
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
558 DataLen = (UINT32) TxData->DataLength;\r
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
587 DEBUG ((EFI_D_ERROR, "SockSend: Failed to buffer IO token into"\r
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
597 DEBUG ((EFI_D_ERROR, "SockSend: Failed to process "\r
598 "Snd Data\n", Status));\r
599\r
600 RemoveEntryList (&(SockToken->TokenList));\r
601 gBS->FreePool (SockToken);\r
602 }\r
603 }\r
604\r
605Exit:\r
606 EfiReleaseLock (&(Sock->Lock));\r
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
643 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
644 if (EFI_ERROR (Status)) {\r
645\r
646 DEBUG ((EFI_D_ERROR, "SockRcv: Get the access for socket"\r
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
720 EfiReleaseLock (&(Sock->Lock));\r
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
743 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
744 if (EFI_ERROR (Status)) {\r
745\r
746 DEBUG ((EFI_D_ERROR, "SockFlush: Get the access for socket"\r
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
759 DEBUG ((EFI_D_ERROR, "SockFlush: Protocol failed handling"\r
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
772 EfiReleaseLock (&(Sock->Lock));\r
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
808 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
809 if (EFI_ERROR (Status)) {\r
810 DEBUG ((EFI_D_ERROR, "SockClose: Get the access for socket"\r
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
848 EfiReleaseLock (&(Sock->Lock));\r
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
895 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
896\r
897 if (EFI_ERROR (Status)) {\r
898\r
899 DEBUG ((EFI_D_ERROR, "SockGroup: Get the access for socket"\r
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
913 EfiReleaseLock (&(Sock->Lock));\r
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
941 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
942 if (EFI_ERROR (Status)) {\r
943 DEBUG ((EFI_D_ERROR, "SockRoute: Get the access for socket"\r
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
962 EfiReleaseLock (&(Sock->Lock));\r
963 return Status;\r
964}\r