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