NetworkPkg: Support TCP Cancel function

This path is used to support TCP Cancel function to abort an
asynchronous connection, listen, transmission or receive request.

If any TCP CompletionToken is not signaled, it should not be closed
directly by calling CloseEvent (Still in the TCP TokenList). If not,
any exception behavior may be triggered. We should cancel it by calling
Tcp->Cancel() first. In such a case, TCP Cancel function is
necessary.

Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com>
Cc: Gary Lin <glin@suse.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Reviewed-by: Gary Lin <glin@suse.com>
Reviewed-by: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Tested-by: Gary Lin <glin@suse.com>
Tested-by: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com>
This commit is contained in:
Jiaxin Wu 2016-05-31 22:17:26 +08:00
parent 3b5624b014
commit 5ffe214ae9
6 changed files with 269 additions and 29 deletions

View File

@ -1,7 +1,7 @@
/** @file
Implementation of the Socket.
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@ -574,6 +574,71 @@ SockWakeRcvToken (
}
}
/**
Cancel the tokens in the specific token list.
@param[in] Token Pointer to the Token. If NULL, all tokens
in SpecifiedTokenList will be canceled.
@param[in, out] SpecifiedTokenList Pointer to the token list to be checked.
@retval EFI_SUCCESS Cancel the tokens in the specific token listsuccessfully.
@retval EFI_NOT_FOUND The Token is not found in SpecifiedTokenList.
**/
EFI_STATUS
SockCancelToken (
IN SOCK_COMPLETION_TOKEN *Token,
IN OUT LIST_ENTRY *SpecifiedTokenList
)
{
EFI_STATUS Status;
LIST_ENTRY *Entry;
LIST_ENTRY *Next;
SOCK_TOKEN *SockToken;
Status = EFI_SUCCESS;
Entry = NULL;
Next = NULL;
SockToken = NULL;
if (IsListEmpty (SpecifiedTokenList) && Token != NULL) {
return EFI_NOT_FOUND;
}
//
// Iterate through the SpecifiedTokenList.
//
Entry = SpecifiedTokenList->ForwardLink;
while (Entry != SpecifiedTokenList) {
SockToken = NET_LIST_USER_STRUCT (Entry, SOCK_TOKEN, TokenList);
if (Token == NULL) {
SIGNAL_TOKEN (SockToken->Token, EFI_ABORTED);
RemoveEntryList (&SockToken->TokenList);
FreePool (SockToken);
Entry = SpecifiedTokenList->ForwardLink;
Status = EFI_SUCCESS;
} else {
if (Token == (VOID *) SockToken->Token) {
SIGNAL_TOKEN (Token, EFI_ABORTED);
RemoveEntryList (&(SockToken->TokenList));
FreePool (SockToken);
return EFI_SUCCESS;
}
Status = EFI_NOT_FOUND;
Entry = Entry->ForwardLink;
}
}
ASSERT (IsListEmpty (SpecifiedTokenList) || Token != NULL);
return Status;
}
/**
Create a socket with initial data SockInitData.

View File

@ -1,7 +1,7 @@
/** @file
The function declaration that provided for Socket Interface.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@ -76,6 +76,23 @@ SockConnFlush (
IN OUT SOCKET *Sock
);
/**
Cancel the tokens in the specific token list.
@param[in] Token Pointer to the Token. If NULL, all tokens
in SpecifiedTokenList will be canceled.
@param[in, out] SpecifiedTokenList Pointer to the token list to be checked.
@retval EFI_SUCCESS Cancel the tokens in the specific token listsuccessfully.
@retval EFI_NOT_FOUND The Token is not found in SpecifiedTokenList.
**/
EFI_STATUS
SockCancelToken (
IN SOCK_COMPLETION_TOKEN *Token,
IN OUT LIST_ENTRY *SpecifiedTokenList
);
/**
Create a socket with initial data SockInitData.

View File

@ -1,7 +1,7 @@
/** @file
Interface function of the Socket.
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@ -876,6 +876,96 @@ Exit:
return Status;
}
/**
Abort the socket associated connection, listen, transmission or receive request.
@param[in, out] Sock Pointer to the socket to abort.
@param[in] Token Pointer to a token that has been issued by
Connect(), Accept(), Transmit() or Receive(). If
NULL, all pending tokens issued by the four
functions listed above will be aborted.
@retval EFI_UNSUPPORTED The operation is not supported in the current
implementation.
**/
EFI_STATUS
SockCancel (
IN OUT SOCKET *Sock,
IN VOID *Token
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
ASSERT (SockStream == Sock->Type);
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG (
(EFI_D_ERROR,
"SockCancel: Get the access for socket failed with %r",
Status)
);
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
//
// 1. Check ConnectionToken.
//
if (Token == NULL || (SOCK_COMPLETION_TOKEN *) Token == Sock->ConnectionToken) {
if (Sock->ConnectionToken != NULL) {
SIGNAL_TOKEN (Sock->ConnectionToken, EFI_ABORTED);
Sock->ConnectionToken = NULL;
}
if (Token != NULL) {
Status = EFI_SUCCESS;
goto Exit;
}
}
//
// 2. Check ListenTokenList.
//
Status = SockCancelToken (Token, &Sock->ListenTokenList);
if (Token != NULL && !EFI_ERROR (Status)) {
goto Exit;
}
//
// 3. Check RcvTokenList.
//
Status = SockCancelToken (Token, &Sock->RcvTokenList);
if (Token != NULL && !EFI_ERROR (Status)) {
goto Exit;
}
//
// 4. Check SndTokenList.
//
Status = SockCancelToken (Token, &Sock->SndTokenList);
if (Token != NULL && !EFI_ERROR (Status)) {
goto Exit;
}
//
// 5. Check ProcessingSndTokenList.
//
Status = SockCancelToken (Token, &Sock->ProcessingSndTokenList);
Exit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}
/**
Get the mode data of the low layer protocol.

View File

@ -1,7 +1,7 @@
/** @file
Common head file for TCP socket.
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@ -864,6 +864,24 @@ SockClose (
IN BOOLEAN OnAbort
);
/**
Abort the socket associated connection, listen, transmission or receive request.
@param[in, out] Sock Pointer to the socket to abort.
@param[in] Token Pointer to a token that has been issued by
Connect(), Accept(), Transmit() or Receive(). If
NULL, all pending tokens issued by the four
functions listed above will be aborted.
@retval EFI_UNSUPPORTED The operation is not supported in the current
implementation.
**/
EFI_STATUS
SockCancel (
IN OUT SOCKET *Sock,
IN VOID *Token
);
/**
Get the mode data of the low layer protocol.

View File

@ -2,7 +2,7 @@
Implementation of EFI_TCP4_PROTOCOL and EFI_TCP6_PROTOCOL.
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@ -484,14 +484,25 @@ Tcp4Close (
/**
Abort an asynchronous connection, listen, transmission or receive request.
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
@param[in] Token Pointer to a token that has been issued by
Connect(), Accept(), Transmit() or Receive(). If
NULL, all pending tokens issued by the four
functions listed above will be aborted.
@param This The pointer to the EFI_TCP4_PROTOCOL instance.
@param Token The pointer to a token that has been issued by
EFI_TCP4_PROTOCOL.Connect(),
EFI_TCP4_PROTOCOL.Accept(),
EFI_TCP4_PROTOCOL.Transmit() or
EFI_TCP4_PROTOCOL.Receive(). If NULL, all pending
tokens issued by above four functions will be aborted. Type
EFI_TCP4_COMPLETION_TOKEN is defined in
EFI_TCP4_PROTOCOL.Connect().
@retval EFI_UNSUPPORTED The operation is not supported in the current
implementation.
@retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event
is signaled.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This instance hasn't been configured.
@retval EFI_NO_MAPPING When using the default address, configuration
(DHCP, BOOTP,RARP, etc.) hasn't finished yet.
@retval EFI_NOT_FOUND The asynchronous I/O request isn't found in the
transmission or receive queue. It has either
completed or wasn't issued by Transmit() and Receive().
**/
EFI_STATUS
@ -501,7 +512,15 @@ Tcp4Cancel (
IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL
)
{
return EFI_UNSUPPORTED;
SOCKET *Sock;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
return SockCancel (Sock, Token);
}
/**
@ -998,20 +1017,20 @@ Tcp6Close (
}
/**
Abort an asynchronous connection, listen, transmission, or receive request.
Abort an asynchronous connection, listen, transmission or receive request.
The Cancel() function aborts a pending connection, listen, transmit, or
The Cancel() function aborts a pending connection, listen, transmit or
receive request.
If Token is not NULL and the token is in the connection, listen, transmission,
If Token is not NULL and the token is in the connection, listen, transmission
or receive queue when it is being cancelled, its Token->Status will be set
to EFI_ABORTED, and then Token->Event will be signaled.
to EFI_ABORTED and then Token->Event will be signaled.
If the token is not in one of the queues, which usually means that the
asynchronous operation has completed, EFI_NOT_FOUND is returned.
If Token is NULL all asynchronous token issued by Connect(), Accept(),
Transmit(), and Receive() will be aborted.
Transmit() and Receive() will be aborted.
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
@param[in] Token Pointer to a token that has been issued by
@ -1023,7 +1042,13 @@ Tcp6Close (
EFI_TCP6_COMPLETION_TOKEN is defined in
EFI_TCP_PROTOCOL.Connect().
@retval EFI_UNSUPPORTED The implementation does not support this function.
@retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event
is signaled.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This instance hasn't been configured.
@retval EFI_NOT_FOUND The asynchronous I/O request isn't found in the transmission or
receive queue. It has either completed or wasn't issued by
Transmit() and Receive().
**/
EFI_STATUS
@ -1033,7 +1058,15 @@ Tcp6Cancel (
IN EFI_TCP6_COMPLETION_TOKEN *Token OPTIONAL
)
{
return EFI_UNSUPPORTED;
SOCKET *Sock;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
return SockCancel (Sock, Token);
}
/**

View File

@ -2,7 +2,7 @@
Declaration of protocol interfaces in EFI_TCP4_PROTOCOL and EFI_TCP6_PROTOCOL.
It is the common head file for all Tcp*.c in TCP driver.
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@ -359,14 +359,25 @@ Tcp4Close (
/**
Abort an asynchronous connection, listen, transmission or receive request.
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
@param[in] Token Pointer to a token that has been issued by
Connect(), Accept(), Transmit() or Receive(). If
NULL, all pending tokens issued by the above four
functions will be aborted.
@param This The pointer to the EFI_TCP4_PROTOCOL instance.
@param Token The pointer to a token that has been issued by
EFI_TCP4_PROTOCOL.Connect(),
EFI_TCP4_PROTOCOL.Accept(),
EFI_TCP4_PROTOCOL.Transmit() or
EFI_TCP4_PROTOCOL.Receive(). If NULL, all pending
tokens issued by above four functions will be aborted. Type
EFI_TCP4_COMPLETION_TOKEN is defined in
EFI_TCP4_PROTOCOL.Connect().
@retval EFI_UNSUPPORTED The operation is not supported in the current
implementation.
@retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event
is signaled.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This instance hasn't been configured.
@retval EFI_NO_MAPPING When using the default address, configuration
(DHCP, BOOTP,RARP, etc.) hasn't finished yet.
@retval EFI_NOT_FOUND The asynchronous I/O request isn't found in the
transmission or receive queue. It has either
completed or wasn't issued by Transmit() and Receive().
**/
EFI_STATUS
@ -730,7 +741,13 @@ Tcp6Close (
EFI_TCP6_COMPLETION_TOKEN is defined in
EFI_TCP_PROTOCOL.Connect().
@retval EFI_UNSUPPORTED The implementation does not support this function.
@retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event
is signaled.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This instance hasn't been configured.
@retval EFI_NOT_FOUND The asynchronous I/O request isn't found in the transmission or
receive queue. It has either completed or wasn't issued by
Transmit() and Receive().
**/
EFI_STATUS