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