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