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