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