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