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