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