Better handle transmit errors

Return 0 receive bytes when socket is closed


git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12099 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lpleahy
2011-08-08 18:19:45 +00:00
parent 42372879b5
commit 1c34b250f6
2 changed files with 250 additions and 223 deletions

View File

@ -2525,91 +2525,18 @@ EslSocketReceive (
pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
// //
// Verify the socket state // Return the transmit error if necessary
// //
if ( !pSocket->bConfigured ) { if ( EFI_SUCCESS != pSocket->TxError ) {
// pSocket->errno = EIO;
// Synchronize with the socket layer Status = pSocket->TxError;
// pSocket->TxError = EFI_SUCCESS;
RAISE_TPL ( TplPrevious, TPL_SOCKETS );
//
// Validate the local address
//
switch ( pSocket->Domain ) {
default:
DEBUG (( DEBUG_RX,
"ERROR - Invalid socket address family: %d\r\n",
pSocket->Domain ));
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL;
break;
case AF_INET:
//
// Determine the connection point within the network stack
//
switch ( pSocket->Type ) {
default:
DEBUG (( DEBUG_RX,
"ERROR - Invalid socket type: %d\r\n",
pSocket->Type));
Status = EFI_INVALID_PARAMETER;
break;
case SOCK_STREAM:
case SOCK_SEQPACKET:
//
// Verify the port state
//
Status = EslTcpSocketIsConfigured4 ( pSocket );
break;
case SOCK_DGRAM:
//
// Verify the port state
//
Status = EslUdpSocketIsConfigured4 ( pSocket );
break;
}
break;
}
//
// Release the socket layer synchronization
//
RESTORE_TPL ( TplPrevious );
//
// Set errno if a failure occurs
//
if ( EFI_ERROR ( Status )) {
pSocket->errno = EADDRNOTAVAIL;
}
} }
if ( !EFI_ERROR ( Status )) { else {
// //
// Validate the buffer length // Verify the socket state
// //
if (( NULL == pDataLength ) if ( !pSocket->bConfigured ) {
&& ( 0 > pDataLength )
&& ( NULL == pBuffer )) {
if ( NULL == pDataLength ) {
DEBUG (( DEBUG_RX,
"ERROR - pDataLength is NULL!\r\n" ));
}
else if ( NULL == pBuffer ) {
DEBUG (( DEBUG_RX,
"ERROR - pBuffer is NULL!\r\n" ));
}
else {
DEBUG (( DEBUG_RX,
"ERROR - Data length < 0!\r\n" ));
}
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EFAULT;
}
else{
// //
// Synchronize with the socket layer // Synchronize with the socket layer
// //
@ -2637,28 +2564,21 @@ EslSocketReceive (
"ERROR - Invalid socket type: %d\r\n", "ERROR - Invalid socket type: %d\r\n",
pSocket->Type)); pSocket->Type));
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL;
break; break;
case SOCK_STREAM: case SOCK_STREAM:
case SOCK_SEQPACKET: case SOCK_SEQPACKET:
Status = EslTcpReceive4 ( pSocket, //
Flags, // Verify the port state
BufferLength, //
pBuffer, Status = EslTcpSocketIsConfigured4 ( pSocket );
pDataLength,
pAddress,
pAddressLength );
break; break;
case SOCK_DGRAM: case SOCK_DGRAM:
Status = EslUdpReceive4 ( pSocket, //
Flags, // Verify the port state
BufferLength, //
pBuffer, Status = EslUdpSocketIsConfigured4 ( pSocket );
pDataLength,
pAddress,
pAddressLength);
break; break;
} }
break; break;
@ -2668,6 +2588,96 @@ EslSocketReceive (
// Release the socket layer synchronization // Release the socket layer synchronization
// //
RESTORE_TPL ( TplPrevious ); RESTORE_TPL ( TplPrevious );
//
// Set errno if a failure occurs
//
if ( EFI_ERROR ( Status )) {
pSocket->errno = EADDRNOTAVAIL;
}
}
if ( !EFI_ERROR ( Status )) {
//
// Validate the buffer length
//
if (( NULL == pDataLength )
&& ( 0 > pDataLength )
&& ( NULL == pBuffer )) {
if ( NULL == pDataLength ) {
DEBUG (( DEBUG_RX,
"ERROR - pDataLength is NULL!\r\n" ));
}
else if ( NULL == pBuffer ) {
DEBUG (( DEBUG_RX,
"ERROR - pBuffer is NULL!\r\n" ));
}
else {
DEBUG (( DEBUG_RX,
"ERROR - Data length < 0!\r\n" ));
}
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EFAULT;
}
else{
//
// Synchronize with the socket layer
//
RAISE_TPL ( TplPrevious, TPL_SOCKETS );
//
// Validate the local address
//
switch ( pSocket->Domain ) {
default:
DEBUG (( DEBUG_RX,
"ERROR - Invalid socket address family: %d\r\n",
pSocket->Domain ));
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL;
break;
case AF_INET:
//
// Determine the connection point within the network stack
//
switch ( pSocket->Type ) {
default:
DEBUG (( DEBUG_RX,
"ERROR - Invalid socket type: %d\r\n",
pSocket->Type));
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL;
break;
case SOCK_STREAM:
case SOCK_SEQPACKET:
Status = EslTcpReceive4 ( pSocket,
Flags,
BufferLength,
pBuffer,
pDataLength,
pAddress,
pAddressLength );
break;
case SOCK_DGRAM:
Status = EslUdpReceive4 ( pSocket,
Flags,
BufferLength,
pBuffer,
pDataLength,
pAddress,
pAddressLength);
break;
}
break;
}
//
// Release the socket layer synchronization
//
RESTORE_TPL ( TplPrevious );
}
} }
} }
} }
@ -2895,171 +2905,181 @@ EslSocketTransmit (
pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
// //
// Verify the socket state // Return the transmit error if necessary
// //
if ( !pSocket->bConfigured ) { if ( EFI_SUCCESS != pSocket->TxError ) {
pSocket->errno = EIO;
Status = pSocket->TxError;
pSocket->TxError = EFI_SUCCESS;
}
else {
// //
// Synchronize with the socket layer // Verify the socket state
// //
RAISE_TPL ( TplPrevious, TPL_SOCKETS ); if ( !pSocket->bConfigured ) {
//
// Validate the local address
//
switch ( pSocket->Domain ) {
default:
DEBUG (( DEBUG_RX,
"ERROR - Invalid socket address family: %d\r\n",
pSocket->Domain ));
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL;
break;
case AF_INET:
// //
// Determine the connection point within the network stack // Synchronize with the socket layer
// //
switch ( pSocket->Type ) { RAISE_TPL ( TplPrevious, TPL_SOCKETS );
//
// Validate the local address
//
switch ( pSocket->Domain ) {
default: default:
DEBUG (( DEBUG_RX, DEBUG (( DEBUG_RX,
"ERROR - Invalid socket type: %d\r\n", "ERROR - Invalid socket address family: %d\r\n",
pSocket->Type)); pSocket->Domain ));
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL;
break; break;
case SOCK_STREAM: case AF_INET:
case SOCK_SEQPACKET:
// //
// Verify the port state // Determine the connection point within the network stack
// //
Status = EslTcpSocketIsConfigured4 ( pSocket ); switch ( pSocket->Type ) {
break; default:
DEBUG (( DEBUG_RX,
"ERROR - Invalid socket type: %d\r\n",
pSocket->Type));
Status = EFI_INVALID_PARAMETER;
break;
case SOCK_DGRAM: case SOCK_STREAM:
// case SOCK_SEQPACKET:
// Verify the port state //
// // Verify the port state
Status = EslUdpSocketIsConfigured4 ( pSocket ); //
Status = EslTcpSocketIsConfigured4 ( pSocket );
break;
case SOCK_DGRAM:
//
// Verify the port state
//
Status = EslUdpSocketIsConfigured4 ( pSocket );
break;
}
break; break;
} }
break;
}
// //
// Release the socket layer synchronization // Release the socket layer synchronization
// //
RESTORE_TPL ( TplPrevious ); RESTORE_TPL ( TplPrevious );
//
// Set errno if a failure occurs
//
if ( EFI_ERROR ( Status )) {
pSocket->errno = EADDRNOTAVAIL;
}
}
if ( !EFI_ERROR ( Status )) {
//
// Verify that transmit is still allowed
//
if ( !pSocket->bTxDisable ) {
// //
// Validate the buffer length // Set errno if a failure occurs
// //
if (( NULL == pDataLength ) if ( EFI_ERROR ( Status )) {
&& ( 0 > pDataLength ) pSocket->errno = EADDRNOTAVAIL;
&& ( NULL == pBuffer )) {
if ( NULL == pDataLength ) {
DEBUG (( DEBUG_RX,
"ERROR - pDataLength is NULL!\r\n" ));
}
else if ( NULL == pBuffer ) {
DEBUG (( DEBUG_RX,
"ERROR - pBuffer is NULL!\r\n" ));
}
else {
DEBUG (( DEBUG_RX,
"ERROR - Data length < 0!\r\n" ));
}
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EFAULT;
} }
else { }
if ( !EFI_ERROR ( Status )) {
//
// Verify that transmit is still allowed
//
if ( !pSocket->bTxDisable ) {
// //
// Validate the remote network address // Validate the buffer length
// //
if (( NULL != pAddress ) if (( NULL == pDataLength )
&& ( AddressLength < pAddress->sa_len )) { && ( 0 > pDataLength )
DEBUG (( DEBUG_TX, && ( NULL == pBuffer )) {
"ERROR - Invalid sin_len field in address\r\n" )); if ( NULL == pDataLength ) {
DEBUG (( DEBUG_RX,
"ERROR - pDataLength is NULL!\r\n" ));
}
else if ( NULL == pBuffer ) {
DEBUG (( DEBUG_RX,
"ERROR - pBuffer is NULL!\r\n" ));
}
else {
DEBUG (( DEBUG_RX,
"ERROR - Data length < 0!\r\n" ));
}
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
pSocket->errno = EFAULT; pSocket->errno = EFAULT;
} }
else { else {
// //
// Synchronize with the socket layer // Validate the remote network address
// //
RAISE_TPL ( TplPrevious, TPL_SOCKETS ); if (( NULL != pAddress )
&& ( AddressLength < pAddress->sa_len )) {
// DEBUG (( DEBUG_TX,
// Validate the local address "ERROR - Invalid sin_len field in address\r\n" ));
//
switch ( pSocket->Domain ) {
default:
DEBUG (( DEBUG_RX,
"ERROR - Invalid socket address family: %d\r\n",
pSocket->Domain ));
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL; pSocket->errno = EFAULT;
break; }
else {
//
// Synchronize with the socket layer
//
RAISE_TPL ( TplPrevious, TPL_SOCKETS );
case AF_INET:
// //
// Determine the connection point within the network stack // Validate the local address
// //
switch ( pSocket->Type ) { switch ( pSocket->Domain ) {
default: default:
DEBUG (( DEBUG_RX, DEBUG (( DEBUG_RX,
"ERROR - Invalid socket type: %d\r\n", "ERROR - Invalid socket address family: %d\r\n",
pSocket->Type)); pSocket->Domain ));
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL; pSocket->errno = EADDRNOTAVAIL;
break; break;
case SOCK_STREAM: case AF_INET:
case SOCK_SEQPACKET: //
Status = EslTcpTxBuffer4 ( pSocket, // Determine the connection point within the network stack
Flags, //
BufferLength, switch ( pSocket->Type ) {
pBuffer, default:
pDataLength ); DEBUG (( DEBUG_RX,
break; "ERROR - Invalid socket type: %d\r\n",
pSocket->Type));
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EADDRNOTAVAIL;
break;
case SOCK_DGRAM: case SOCK_STREAM:
Status = EslUdpTxBuffer4 ( pSocket, case SOCK_SEQPACKET:
Flags, Status = EslTcpTxBuffer4 ( pSocket,
BufferLength, Flags,
pBuffer, BufferLength,
pDataLength, pBuffer,
pAddress, pDataLength );
AddressLength ); break;
case SOCK_DGRAM:
Status = EslUdpTxBuffer4 ( pSocket,
Flags,
BufferLength,
pBuffer,
pDataLength,
pAddress,
AddressLength );
break;
}
break; break;
} }
break;
}
// //
// Release the socket layer synchronization // Release the socket layer synchronization
// //
RESTORE_TPL ( TplPrevious ); RESTORE_TPL ( TplPrevious );
}
} }
} }
} else {
else { //
// // The transmitter was shutdown
// The transmitter was shutdown //
// pSocket->errno = EPIPE;
pSocket->errno = EPIPE; Status = EFI_NOT_STARTED;
Status = EFI_NOT_STARTED; }
} }
} }
} }

View File

@ -2448,13 +2448,21 @@ EslTcpReceive4 (
&& ( NULL == pSocket->pRxPacketListHead ) && ( NULL == pSocket->pRxPacketListHead )
&& ( NULL == pSocket->pRxOobPacketListHead )) { && ( NULL == pSocket->pRxOobPacketListHead )) {
Status = pSocket->RxError; Status = pSocket->RxError;
pSocket->RxError = EFI_SUCCESS;
switch ( Status ) { switch ( Status ) {
default: default:
pSocket->errno = EIO; pSocket->errno = EIO;
break; break;
case EFI_CONNECTION_FIN: case EFI_CONNECTION_FIN:
pSocket->errno = ESHUTDOWN; //
// Continue to return zero bytes received when the
// peer has successfully closed the connection
//
pSocket->RxError = EFI_CONNECTION_FIN;
*pDataLength = 0;
pSocket->errno = 0;
Status = EFI_SUCCESS;
break; break;
case EFI_CONNECTION_REFUSED: case EFI_CONNECTION_REFUSED:
@ -2481,7 +2489,6 @@ EslTcpReceive4 (
pSocket->errno = ENOPROTOOPT; pSocket->errno = ENOPROTOOPT;
break; break;
} }
pSocket->RxError = EFI_SUCCESS;
} }
else { else {
Status = EFI_NOT_READY; Status = EFI_NOT_READY;