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