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