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