]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TcpDxe/SockInterface.c
IntelFsp2Pkg: Removing FSP Data Table
[mirror_edk2.git] / NetworkPkg / TcpDxe / SockInterface.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Interface function of the Socket.\r
3\r
5ffe214a 4 Copyright (c) 2009 - 2016, 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
f3612a8d 473 (EFI_D_NET,\r
a3bcde70
HT
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
72a4f34e 727 SockProcessRcvToken (Sock, RcvToken);\r
a3bcde70
HT
728\r
729 Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);\r
730 } else {\r
731\r
732 if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {\r
733 Status = EFI_OUT_OF_RESOURCES;\r
734 }\r
735 }\r
736\r
737Exit:\r
738 EfiReleaseLock (&(Sock->Lock));\r
739 return Status;\r
740}\r
741\r
742/**\r
743 Reset the socket and its associated protocol control block.\r
744\r
745 @param[in, out] Sock Pointer to the socket to be flushed.\r
746\r
747 @retval EFI_SUCCESS The socket is flushed successfully.\r
748 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
749\r
750**/\r
751EFI_STATUS\r
752SockFlush (\r
753 IN OUT SOCKET *Sock\r
754 )\r
755{\r
756 EFI_STATUS Status;\r
757\r
758 ASSERT (SockStream == Sock->Type);\r
759\r
760 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
761 if (EFI_ERROR (Status)) {\r
762\r
763 DEBUG (\r
764 (EFI_D_ERROR,\r
765 "SockFlush: Get the access for socket failed with %r",\r
766 Status)\r
767 );\r
768\r
769 return EFI_ACCESS_DENIED;\r
770 }\r
771\r
772 if (!SOCK_IS_CONFIGURED (Sock)) {\r
773\r
774 Status = EFI_ACCESS_DENIED;\r
775 goto Exit;\r
776 }\r
777\r
778 Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);\r
779 if (EFI_ERROR (Status)) {\r
780\r
781 DEBUG (\r
782 (EFI_D_ERROR,\r
783 "SockFlush: Protocol failed handling SOCK_FLUSH with %r",\r
784 Status)\r
785 );\r
786\r
787 goto Exit;\r
788 }\r
789\r
790 SOCK_ERROR (Sock, EFI_ABORTED);\r
791 SockConnFlush (Sock);\r
792 SockSetState (Sock, SO_CLOSED);\r
793\r
794 Sock->ConfigureState = SO_UNCONFIGURED;\r
795\r
796Exit:\r
797 EfiReleaseLock (&(Sock->Lock));\r
798 return Status;\r
799}\r
800\r
801/**\r
802 Close or abort the socket associated connection.\r
803\r
804 @param[in, out] Sock Pointer to the socket of the connection to close\r
805 or abort.\r
806 @param[in] Token The token for a close operation.\r
807 @param[in] OnAbort TRUE for aborting the connection; FALSE to close it.\r
808\r
809 @retval EFI_SUCCESS The close or abort operation initialized\r
810 successfully.\r
811 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
812 socket is closed, or the socket is not in a\r
813 synchronized state , or the token is already in one\r
814 of this socket's lists.\r
815 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
816 finished.\r
817 @retval EFI_NOT_STARTED The socket is not configured.\r
818\r
819**/\r
820EFI_STATUS\r
821SockClose (\r
822 IN OUT SOCKET *Sock,\r
823 IN VOID *Token,\r
824 IN BOOLEAN OnAbort\r
825 )\r
826{\r
827 EFI_STATUS Status;\r
828 EFI_EVENT Event;\r
829\r
830 ASSERT (SockStream == Sock->Type);\r
831\r
832 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
833 if (EFI_ERROR (Status)) {\r
834 DEBUG (\r
835 (EFI_D_ERROR,\r
836 "SockClose: Get the access for socket failed with %r",\r
837 Status)\r
838 );\r
839\r
840 return EFI_ACCESS_DENIED;\r
841 }\r
842\r
843 if (SOCK_IS_NO_MAPPING (Sock)) {\r
844 Status = EFI_NO_MAPPING;\r
845 goto Exit;\r
846 }\r
847\r
848 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
849 Status = EFI_NOT_STARTED;\r
850 goto Exit;\r
851 }\r
852\r
853 if (SOCK_IS_DISCONNECTING (Sock)) {\r
854 Status = EFI_ACCESS_DENIED;\r
855 goto Exit;\r
856 }\r
857\r
858 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
859\r
860 if (SockTokenExisted (Sock, Event)) {\r
861 Status = EFI_ACCESS_DENIED;\r
862 goto Exit;\r
863 }\r
864\r
865 Sock->CloseToken = Token;\r
866 SockSetState (Sock, SO_DISCONNECTING);\r
867\r
868 if (OnAbort) {\r
869 Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);\r
870 } else {\r
871 Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);\r
872 }\r
873\r
874Exit:\r
875 EfiReleaseLock (&(Sock->Lock));\r
876 return Status;\r
877}\r
878\r
5ffe214a
JW
879/**\r
880 Abort the socket associated connection, listen, transmission or receive request.\r
881\r
882 @param[in, out] Sock Pointer to the socket to abort.\r
883 @param[in] Token Pointer to a token that has been issued by\r
884 Connect(), Accept(), Transmit() or Receive(). If\r
885 NULL, all pending tokens issued by the four\r
886 functions listed above will be aborted.\r
887\r
888 @retval EFI_UNSUPPORTED The operation is not supported in the current\r
889 implementation.\r
890**/\r
891EFI_STATUS\r
892SockCancel (\r
893 IN OUT SOCKET *Sock,\r
894 IN VOID *Token\r
895 ) \r
896{\r
897 EFI_STATUS Status;\r
898\r
899 Status = EFI_SUCCESS;\r
900\r
901 ASSERT (SockStream == Sock->Type);\r
902\r
903 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
904 if (EFI_ERROR (Status)) {\r
905 DEBUG (\r
906 (EFI_D_ERROR,\r
907 "SockCancel: Get the access for socket failed with %r",\r
908 Status)\r
909 );\r
910\r
911 return EFI_ACCESS_DENIED;\r
912 }\r
913\r
914 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
915 Status = EFI_NOT_STARTED;\r
916 goto Exit;\r
917 }\r
918 \r
919 //\r
920 // 1. Check ConnectionToken.\r
921 //\r
922 if (Token == NULL || (SOCK_COMPLETION_TOKEN *) Token == Sock->ConnectionToken) {\r
923 if (Sock->ConnectionToken != NULL) {\r
924 SIGNAL_TOKEN (Sock->ConnectionToken, EFI_ABORTED);\r
925 Sock->ConnectionToken = NULL;\r
926 }\r
927\r
928 if (Token != NULL) {\r
929 Status = EFI_SUCCESS;\r
930 goto Exit;\r
931 }\r
932 }\r
933\r
934 //\r
935 // 2. Check ListenTokenList.\r
936 //\r
937 Status = SockCancelToken (Token, &Sock->ListenTokenList);\r
938 if (Token != NULL && !EFI_ERROR (Status)) {\r
939 goto Exit;\r
940 }\r
941\r
942 //\r
943 // 3. Check RcvTokenList.\r
944 //\r
945 Status = SockCancelToken (Token, &Sock->RcvTokenList);\r
946 if (Token != NULL && !EFI_ERROR (Status)) {\r
947 goto Exit;\r
948 }\r
949 \r
950 //\r
951 // 4. Check SndTokenList.\r
952 //\r
953 Status = SockCancelToken (Token, &Sock->SndTokenList);\r
954 if (Token != NULL && !EFI_ERROR (Status)) {\r
955 goto Exit;\r
956 }\r
957\r
958 //\r
959 // 5. Check ProcessingSndTokenList.\r
960 //\r
961 Status = SockCancelToken (Token, &Sock->ProcessingSndTokenList);\r
962 \r
963Exit:\r
964 EfiReleaseLock (&(Sock->Lock));\r
965 return Status;\r
966}\r
967\r
968\r
a3bcde70
HT
969/**\r
970 Get the mode data of the low layer protocol.\r
971\r
972 @param[in] Sock Pointer to the socket to get mode data from.\r
973 @param[in, out] Mode Pointer to the data to store the low layer mode\r
974 information.\r
975\r
976 @retval EFI_SUCCESS The mode data was obtained successfully.\r
977 @retval EFI_NOT_STARTED The socket is not configured.\r
978\r
979**/\r
980EFI_STATUS\r
981SockGetMode (\r
982 IN SOCKET *Sock,\r
983 IN OUT VOID *Mode\r
984 )\r
985{\r
986 return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);\r
987}\r
988\r
989/**\r
990 Configure the low level protocol to join a multicast group for\r
991 this socket's connection.\r
992\r
993 @param[in] Sock Pointer to the socket of the connection to join the\r
994 specific multicast group.\r
995 @param[in] GroupInfo Pointer to the multicast group info.\r
996\r
997 @retval EFI_SUCCESS The configuration completed successfully.\r
998 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
999 @retval EFI_NOT_STARTED The socket is not configured.\r
1000\r
1001**/\r
1002EFI_STATUS\r
1003SockGroup (\r
1004 IN SOCKET *Sock,\r
1005 IN VOID *GroupInfo\r
1006 )\r
1007{\r
1008 EFI_STATUS Status;\r
1009\r
1010 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
1011\r
1012 if (EFI_ERROR (Status)) {\r
1013\r
1014 DEBUG (\r
1015 (EFI_D_ERROR,\r
1016 "SockGroup: Get the access for socket failed with %r",\r
1017 Status)\r
1018 );\r
1019\r
1020 return EFI_ACCESS_DENIED;\r
1021 }\r
1022\r
1023 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
1024 Status = EFI_NOT_STARTED;\r
1025 goto Exit;\r
1026 }\r
1027\r
1028 Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);\r
1029\r
1030Exit:\r
1031 EfiReleaseLock (&(Sock->Lock));\r
1032 return Status;\r
1033}\r
1034\r
1035/**\r
1036 Add or remove route information in IP route table associated\r
1037 with this socket.\r
1038\r
1039 @param[in] Sock Pointer to the socket associated with the IP route\r
1040 table to operate on.\r
1041 @param[in] RouteInfo Pointer to the route information to be processed.\r
1042\r
1043 @retval EFI_SUCCESS The route table updated successfully.\r
1044 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
1045 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
1046 finished.\r
1047 @retval EFI_NOT_STARTED The socket is not configured.\r
1048\r
1049**/\r
1050EFI_STATUS\r
1051SockRoute (\r
1052 IN SOCKET *Sock,\r
1053 IN VOID *RouteInfo\r
1054 )\r
1055{\r
1056 EFI_STATUS Status;\r
1057\r
1058 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
1059 if (EFI_ERROR (Status)) {\r
1060 DEBUG (\r
1061 (EFI_D_ERROR,\r
1062 "SockRoute: Get the access for socket failed with %r",\r
1063 Status)\r
1064 );\r
1065\r
1066 return EFI_ACCESS_DENIED;\r
1067 }\r
1068\r
1069 if (SOCK_IS_NO_MAPPING (Sock)) {\r
1070 Status = EFI_NO_MAPPING;\r
1071 goto Exit;\r
1072 }\r
1073\r
1074 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
1075 Status = EFI_NOT_STARTED;\r
1076 goto Exit;\r
1077 }\r
1078\r
1079 Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);\r
1080\r
1081Exit:\r
1082 EfiReleaseLock (&(Sock->Lock));\r
1083 return Status;\r
1084}\r
1085\r