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