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