diff options
author | vanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524> | 2007-07-24 08:06:37 +0000 |
---|---|---|
committer | vanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524> | 2007-07-24 08:06:37 +0000 |
commit | 8a67d61da4d5a8f08a656cbeea2d902d0ad9042a (patch) | |
tree | 6618049196a9f4a206b8d6e42fb8b67a71558503 /MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c | |
parent | f9bef4b3ac2bf3bd5f79313f772519800761f104 (diff) | |
download | edk2-platforms-8a67d61da4d5a8f08a656cbeea2d902d0ad9042a.tar.xz |
Import SnpDxe, Tcp4Dxe, Udp4Dxe and MnpDxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3416 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c')
-rw-r--r-- | MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c | 980 |
1 files changed, 980 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c b/MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c new file mode 100644 index 0000000000..0b71996e14 --- /dev/null +++ b/MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c @@ -0,0 +1,980 @@ +/** @file
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SockInterface.c
+
+Abstract:
+
+
+**/
+
+
+#include "SockImpl.h"
+
+
+/**
+ Check whether the Event is in the List.
+
+ @param List Pointer to the token list to be searched.
+ @param Event The event to be checked.
+
+ @retval BOOLEAN If TRUE, the specific Event exists in the List. If
+ FALSE, the specific Event is not in the List.
+
+**/
+STATIC
+BOOLEAN
+SockTokenExistedInList (
+ IN NET_LIST_ENTRY *List,
+ IN EFI_EVENT Event
+ )
+{
+ NET_LIST_ENTRY *ListEntry;
+ SOCK_TOKEN *SockToken;
+
+ NET_LIST_FOR_EACH (ListEntry, List) {
+ SockToken = NET_LIST_USER_STRUCT (
+ ListEntry,
+ SOCK_TOKEN,
+ TokenList
+ );
+
+ if (Event == SockToken->Token->Event) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Call SockTokenExistedInList() to check whether the Event is
+ in the related socket's lists.
+
+ @param Sock Pointer to the instance's socket.
+ @param Event The event to be checked.
+
+ @return The specific Event exists in one of socket's lists or not.
+
+**/
+BOOLEAN
+SockTokenExisted (
+ IN SOCKET *Sock,
+ IN EFI_EVENT Event
+ )
+{
+
+ if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||
+ SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||
+ SockTokenExistedInList (&Sock->RcvTokenList, Event) ||
+ SockTokenExistedInList (&Sock->ListenTokenList, Event)
+ ) {
+
+ return TRUE;
+ }
+
+ if ((Sock->ConnectionToken != NULL) &&
+ (Sock->ConnectionToken->Event == Event)) {
+
+ return TRUE;
+ }
+
+ if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Buffer a token into the specific list of socket Sock.
+
+ @param Sock Pointer to the instance's socket.
+ @param List Pointer to the list to store the token.
+ @param Token Pointer to the token to be buffered.
+ @param DataLen The data length of the buffer contained in Token.
+
+ @return Pointer to the token that wraps Token. If NULL, error condition occurred.
+
+**/
+SOCK_TOKEN *
+SockBufferToken (
+ IN SOCKET *Sock,
+ IN NET_LIST_ENTRY *List,
+ IN VOID *Token,
+ IN UINT32 DataLen
+ )
+{
+ SOCK_TOKEN *SockToken;
+
+ SockToken = NetAllocatePool (sizeof (SOCK_TOKEN));
+ if (NULL == SockToken) {
+
+ SOCK_DEBUG_ERROR (("SockBufferIOToken: No Memory "
+ "to allocate SockToken\n"));
+
+ return NULL;
+ }
+
+ SockToken->Sock = Sock;
+ SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;
+ SockToken->RemainDataLen = DataLen;
+ NetListInsertTail (List, &SockToken->TokenList);
+
+ return SockToken;
+}
+
+
+/**
+ Destory the socket Sock and its associated protocol control block.
+
+ @param Sock The socket to be destroyed.
+
+ @retval EFI_SUCCESS The socket Sock is destroyed successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
+
+**/
+EFI_STATUS
+SockDestroyChild (
+ IN SOCKET *Sock
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (Sock && Sock->ProtoHandler);
+
+ if (Sock->IsDestroyed) {
+ return EFI_SUCCESS;
+ }
+
+ Sock->IsDestroyed = TRUE;
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockDestroyChild: Get the lock to "
+ "access socket failed with %r\n", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // force protocol layer to detach the PCB
+ //
+ Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);
+
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockDestroyChild: Protocol detach socket"
+ " failed with %r\n", Status));
+
+ Sock->IsDestroyed = FALSE;
+ } else if (SOCK_IS_CONFIGURED (Sock)) {
+
+ SockConnFlush (Sock);
+ SockSetState (Sock, SO_CLOSED);
+
+ Sock->ConfigureState = SO_UNCONFIGURED;
+ }
+
+ NET_UNLOCK (&(Sock->Lock));
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SockDestroy (Sock);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Create a socket and its associated protocol control block
+ with the intial data SockInitData and protocol specific
+ data ProtoData.
+
+ @param SockInitData Inital data to setting the socket.
+ @param ProtoData Pointer to the protocol specific data.
+ @param Len Length of the protocol specific data.
+
+ @return Pointer to the newly created socket. If NULL, error condition occured.
+
+**/
+SOCKET *
+SockCreateChild (
+ IN SOCK_INIT_DATA *SockInitData,
+ IN VOID *ProtoData,
+ IN UINT32 Len
+ )
+{
+ SOCKET *Sock;
+ EFI_STATUS Status;
+
+ ASSERT (ProtoData && (Len <= PROTO_RESERVED_LEN));
+
+ //
+ // create a new socket
+ //
+ Sock = SockCreate (SockInitData);
+ if (NULL == Sock) {
+
+ SOCK_DEBUG_ERROR (("SockCreateChild: No resource to "
+ "create a new socket\n"));
+
+ return NULL;
+ }
+
+ //
+ // Open the
+ //
+
+ //
+ // copy the protodata into socket
+ //
+ NetCopyMem (Sock->ProtoReserved, ProtoData, Len);
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockCreateChild: Get the lock to "
+ "access socket failed with %r\n", Status));
+
+ SockDestroy (Sock);
+ return NULL;
+ }
+ //
+ // inform the protocol layer to attach the socket
+ // with a new protocol control block
+ //
+ Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockCreateChild: Protocol failed to"
+ " attach a socket with %r\n", Status));
+
+ SockDestroy (Sock);
+ Sock = NULL;
+ }
+
+ NET_UNLOCK (&(Sock->Lock));
+ return Sock;
+}
+
+
+/**
+ Configure the specific socket Sock using configuration data
+ ConfigData.
+
+ @param Sock Pointer to the socket to be configured.
+ @param ConfigData Pointer to the configuration data.
+
+ @retval EFI_SUCCESS The socket is configured successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
+ socket is already configured.
+
+**/
+EFI_STATUS
+SockConfigure (
+ IN SOCKET *Sock,
+ IN VOID *ConfigData
+ )
+{
+ EFI_STATUS Status;
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockConfigure: Get the access for "
+ "socket failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (SOCK_IS_CONFIGURED (Sock)) {
+ Status = EFI_ACCESS_DENIED;
+ goto OnExit;
+ }
+
+ ASSERT (Sock->State == SO_CLOSED);
+
+ Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);
+
+OnExit:
+ NET_UNLOCK (&(Sock->Lock));
+
+ return Status;
+}
+
+
+/**
+ Initiate a connection establishment process.
+
+ @param Sock Pointer to the socket to initiate the initate the
+ connection.
+ @param Token Pointer to the token used for the connection
+ operation.
+
+ @retval EFI_SUCCESS The connection is initialized successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
+ socket is closed, or the socket is not configured to
+ be an active one, or the token is already in one of
+ this socket's lists.
+ @retval EFI_NO_MAPPING The IP address configuration operation is not
+ finished.
+ @retval EFI_NOT_STARTED The socket is not configured.
+
+**/
+EFI_STATUS
+SockConnect (
+ IN SOCKET *Sock,
+ IN VOID *Token
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockConnect: Get the access for "
+ "socket failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (SOCK_IS_NO_MAPPING (Sock)) {
+ Status = EFI_NO_MAPPING;
+ goto OnExit;
+ }
+
+ if (SOCK_IS_UNCONFIGURED (Sock)) {
+
+ Status = EFI_NOT_STARTED;
+ goto OnExit;
+ }
+
+ if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {
+
+ Status = EFI_ACCESS_DENIED;
+ goto OnExit;
+ }
+
+ Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
+
+ if (SockTokenExisted (Sock, Event)) {
+
+ Status = EFI_ACCESS_DENIED;
+ goto OnExit;
+ }
+
+ Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;
+ SockSetState (Sock, SO_CONNECTING);
+ Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);
+
+OnExit:
+ NET_UNLOCK (&(Sock->Lock));
+ return Status;
+}
+
+
+/**
+ Issue a listen token to get an existed connected network instance
+ or wait for a connection if there is none.
+
+ @param Sock Pointer to the socket to accept connections.
+ @param Token The token to accept a connection.
+
+ @retval EFI_SUCCESS Either a connection is accpeted or the Token is
+ buffered for further acception.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
+ socket is closed, or the socket is not configured to
+ be a passive one, or the token is already in one of
+ this socket's lists.
+ @retval EFI_NO_MAPPING The IP address configuration operation is not
+ finished.
+ @retval EFI_NOT_STARTED The socket is not configured.
+ @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
+
+**/
+EFI_STATUS
+SockAccept (
+ IN SOCKET *Sock,
+ IN VOID *Token
+ )
+{
+ EFI_TCP4_LISTEN_TOKEN *ListenToken;
+ NET_LIST_ENTRY *ListEntry;
+ EFI_STATUS Status;
+ SOCKET *Socket;
+ EFI_EVENT Event;
+
+ ASSERT (SOCK_STREAM == Sock->Type);
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockAccept: Get the access for socket"
+ " failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (SOCK_IS_NO_MAPPING (Sock)) {
+ Status = EFI_NO_MAPPING;
+ goto Exit;
+ }
+
+ if (SOCK_IS_UNCONFIGURED (Sock)) {
+
+ Status = EFI_NOT_STARTED;
+ goto Exit;
+ }
+
+ if (!SOCK_IS_LISTENING (Sock)) {
+
+ Status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
+
+ if (SockTokenExisted (Sock, Event)) {
+
+ Status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;
+
+ //
+ // Check if a connection has already in this Sock->ConnectionList
+ //
+ NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {
+
+ Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);
+
+ if (SOCK_IS_CONNECTED (Socket)) {
+ ListenToken->NewChildHandle = Socket->SockHandle;
+ SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
+
+ NetListRemoveEntry (ListEntry);
+
+ ASSERT (Socket->Parent);
+
+ Socket->Parent->ConnCnt--;
+
+ SOCK_DEBUG_WARN (("SockAccept: Accept a socket,"
+ "now conncount is %d", Socket->Parent->ConnCnt)
+ );
+ Socket->Parent = NULL;
+
+ goto Exit;
+ }
+ }
+
+ //
+ // Buffer this token for latter incoming connection request
+ //
+ if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {
+
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+
+Exit:
+ NET_UNLOCK (&(Sock->Lock));
+
+ return Status;
+}
+
+
+/**
+ Issue a token with data to the socket to send out.
+
+ @param Sock Pointer to the socket to process the token with
+ data.
+ @param Token The token with data that needs to send out.
+
+ @retval EFI_SUCCESS The token is processed successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
+ socket is closed, or the socket is not in a
+ synchronized state , or the token is already in one
+ of this socket's lists.
+ @retval EFI_NO_MAPPING The IP address configuration operation is not
+ finished.
+ @retval EFI_NOT_STARTED The socket is not configured.
+ @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
+
+**/
+EFI_STATUS
+SockSend (
+ IN SOCKET *Sock,
+ IN VOID *Token
+ )
+{
+ SOCK_IO_TOKEN *SndToken;
+ EFI_EVENT Event;
+ UINT32 FreeSpace;
+ EFI_TCP4_TRANSMIT_DATA *TxData;
+ EFI_STATUS Status;
+ SOCK_TOKEN *SockToken;
+ UINT32 DataLen;
+
+ ASSERT (SOCK_STREAM == Sock->Type);
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockSend: Get the access for socket"
+ " failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (SOCK_IS_NO_MAPPING (Sock)) {
+ Status = EFI_NO_MAPPING;
+ goto Exit;
+ }
+
+ SndToken = (SOCK_IO_TOKEN *) Token;
+ TxData = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;
+
+ if (SOCK_IS_UNCONFIGURED (Sock)) {
+ Status = EFI_NOT_STARTED;
+ goto Exit;
+ }
+
+ if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {
+
+ Status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ //
+ // check if a token is already in the token buffer
+ //
+ Event = SndToken->Token.Event;
+
+ if (SockTokenExisted (Sock, Event)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ DataLen = TxData->DataLength;
+
+ //
+ // process this sending token now or buffer it only?
+ //
+ FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
+
+ if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {
+
+ SockToken = SockBufferToken (
+ Sock,
+ &Sock->SndTokenList,
+ SndToken,
+ DataLen
+ );
+
+ if (NULL == SockToken) {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+
+ SockToken = SockBufferToken (
+ Sock,
+ &Sock->ProcessingSndTokenList,
+ SndToken,
+ DataLen
+ );
+
+ if (NULL == SockToken) {
+ SOCK_DEBUG_ERROR (("SockSend: Failed to buffer IO token into"
+ " socket processing SndToken List\n", Status));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Status = SockProcessTcpSndData (Sock, TxData);
+
+ if (EFI_ERROR (Status)) {
+ SOCK_DEBUG_ERROR (("SockSend: Failed to process "
+ "Snd Data\n", Status));
+
+ NetListRemoveEntry (&(SockToken->TokenList));
+ NetFreePool (SockToken);
+ }
+ }
+
+Exit:
+ NET_UNLOCK (&(Sock->Lock));
+ return Status;
+}
+
+
+/**
+ Issue a token to get data from the socket.
+
+ @param Sock Pointer to the socket to get data from.
+ @param Token The token to store the received data from the
+ socket.
+
+ @retval EFI_SUCCESS The token is processed successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
+ socket is closed, or the socket is not in a
+ synchronized state , or the token is already in one
+ of this socket's lists.
+ @retval EFI_NO_MAPPING The IP address configuration operation is not
+ finished.
+ @retval EFI_NOT_STARTED The socket is not configured.
+ @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
+ @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
+
+**/
+EFI_STATUS
+SockRcv (
+ IN SOCKET *Sock,
+ IN VOID *Token
+ )
+{
+ SOCK_IO_TOKEN *RcvToken;
+ UINT32 RcvdBytes;
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ ASSERT (SOCK_STREAM == Sock->Type);
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockRcv: Get the access for socket"
+ " failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (SOCK_IS_NO_MAPPING (Sock)) {
+
+ Status = EFI_NO_MAPPING;
+ goto Exit;
+ }
+
+ if (SOCK_IS_UNCONFIGURED (Sock)) {
+
+ Status = EFI_NOT_STARTED;
+ goto Exit;
+ }
+
+ if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {
+
+ Status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ RcvToken = (SOCK_IO_TOKEN *) Token;
+
+ //
+ // check if a token is already in the token buffer of this socket
+ //
+ Event = RcvToken->Token.Event;
+ if (SockTokenExisted (Sock, Event)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ RcvToken = (SOCK_IO_TOKEN *) Token;
+ RcvdBytes = GET_RCV_DATASIZE (Sock);
+
+ //
+ // check whether an error has happened before
+ //
+ if (EFI_ABORTED != Sock->SockError) {
+
+ SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);
+ Sock->SockError = EFI_ABORTED;
+ goto Exit;
+ }
+
+ //
+ // check whether can not receive and there is no any
+ // data buffered in Sock->RcvBuffer
+ //
+ if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {
+
+ Status = EFI_CONNECTION_FIN;
+ goto Exit;
+ }
+
+ if (RcvdBytes != 0) {
+ Status = SockProcessRcvToken (Sock, RcvToken);
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);
+ } else {
+
+ if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+Exit:
+ NET_UNLOCK (&(Sock->Lock));
+ return Status;
+}
+
+
+/**
+ Reset the socket and its associated protocol control block.
+
+ @param Sock Pointer to the socket to be flushed.
+
+ @retval EFI_SUCCESS The socket is flushed successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
+
+**/
+EFI_STATUS
+SockFlush (
+ IN SOCKET *Sock
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (SOCK_STREAM == Sock->Type);
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockFlush: Get the access for socket"
+ " failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (!SOCK_IS_CONFIGURED (Sock)) {
+ goto Exit;
+ }
+
+ Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockFlush: Protocol failed handling"
+ " SOCK_FLUSH with %r", Status));
+
+ goto Exit;
+ }
+
+ SOCK_ERROR (Sock, EFI_ABORTED);
+ SockConnFlush (Sock);
+ SockSetState (Sock, SO_CLOSED);
+
+ Sock->ConfigureState = SO_UNCONFIGURED;
+
+Exit:
+ NET_UNLOCK (&(Sock->Lock));
+ return Status;
+}
+
+
+/**
+ Close or abort the socket associated connection.
+
+ @param Sock Pointer to the socket of the connection to close or
+ abort.
+ @param Token The token for close operation.
+ @param OnAbort TRUE for aborting the connection, FALSE to close it.
+
+ @retval EFI_SUCCESS The close or abort operation is initialized
+ successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
+ socket is closed, or the socket is not in a
+ synchronized state , or the token is already in one
+ of this socket's lists.
+ @retval EFI_NO_MAPPING The IP address configuration operation is not
+ finished.
+ @retval EFI_NOT_STARTED The socket is not configured.
+
+**/
+EFI_STATUS
+SockClose (
+ IN SOCKET *Sock,
+ IN VOID *Token,
+ IN BOOLEAN OnAbort
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ ASSERT (SOCK_STREAM == Sock->Type);
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+ SOCK_DEBUG_ERROR (("SockClose: Get the access for socket"
+ " failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (SOCK_IS_NO_MAPPING (Sock)) {
+ Status = EFI_NO_MAPPING;
+ goto Exit;
+ }
+
+ if (SOCK_IS_UNCONFIGURED (Sock)) {
+ Status = EFI_NOT_STARTED;
+ goto Exit;
+ }
+
+ if (SOCK_IS_DISCONNECTING (Sock)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
+
+ if (SockTokenExisted (Sock, Event)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ Sock->CloseToken = Token;
+ SockSetState (Sock, SO_DISCONNECTING);
+
+ if (OnAbort) {
+ Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);
+ } else {
+ Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);
+ }
+
+Exit:
+ NET_UNLOCK (&(Sock->Lock));
+ return Status;
+}
+
+
+/**
+ Get the mode data of the low layer protocol.
+
+ @param Sock Pointer to the socket to get mode data from.
+ @param Mode Pointer to the data to store the low layer mode
+ information.
+
+ @retval EFI_SUCCESS The mode data is got successfully.
+ @retval EFI_NOT_STARTED The socket is not configured.
+
+**/
+EFI_STATUS
+SockGetMode (
+ IN SOCKET *Sock,
+ IN VOID *Mode
+ )
+{
+ return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);
+}
+
+
+/**
+ Configure the low level protocol to join a multicast group for
+ this socket's connection.
+
+ @param Sock Pointer to the socket of the connection to join the
+ specific multicast group.
+ @param GroupInfo Pointer to the multicast group info.
+
+ @retval EFI_SUCCESS The configuration is done successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
+ @retval EFI_NOT_STARTED The socket is not configured.
+
+**/
+EFI_STATUS
+SockGroup (
+ IN SOCKET *Sock,
+ IN VOID *GroupInfo
+ )
+{
+ EFI_STATUS Status;
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+
+ if (EFI_ERROR (Status)) {
+
+ SOCK_DEBUG_ERROR (("SockGroup: Get the access for socket"
+ " failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (SOCK_IS_UNCONFIGURED (Sock)) {
+ Status = EFI_NOT_STARTED;
+ goto Exit;
+ }
+
+ Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);
+
+Exit:
+ NET_UNLOCK (&(Sock->Lock));
+ return Status;
+}
+
+
+/**
+ Add or remove route information in IP route table associated
+ with this socket.
+
+ @param Sock Pointer to the socket associated with the IP route
+ table to operate on.
+ @param RouteInfo Pointer to the route information to be processed.
+
+ @retval EFI_SUCCESS The route table is updated successfully.
+ @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
+ @retval EFI_NO_MAPPING The IP address configuration operation is not
+ finished.
+ @retval EFI_NOT_STARTED The socket is not configured.
+
+**/
+EFI_STATUS
+SockRoute (
+ IN SOCKET *Sock,
+ IN VOID *RouteInfo
+ )
+{
+ EFI_STATUS Status;
+
+ Status = NET_TRYLOCK (&(Sock->Lock));
+ if (EFI_ERROR (Status)) {
+ SOCK_DEBUG_ERROR (("SockRoute: Get the access for socket"
+ " failed with %r", Status));
+
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (SOCK_IS_NO_MAPPING (Sock)) {
+ Status = EFI_NO_MAPPING;
+ goto Exit;
+ }
+
+ if (SOCK_IS_UNCONFIGURED (Sock)) {
+ Status = EFI_NOT_STARTED;
+ goto Exit;
+ }
+
+ Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);
+
+Exit:
+ NET_UNLOCK (&(Sock->Lock));
+ return Status;
+}
|