summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-19 23:13:41 +0000
committerlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-19 23:13:41 +0000
commit855f5eb0eb0d2a68d2d86f4c39955b5ab513f0a1 (patch)
treee7fb6fa975084c75a4bfee80694e37a68037a72d
parent5ee61664c75bab3bbd1cad581e674ab90d0c87ac (diff)
downloadedk2-855f5eb0eb0d2a68d2d86f4c39955b5ab513f0a1.zip
edk2-855f5eb0eb0d2a68d2d86f4c39955b5ab513f0a1.tar.gz
edk2-855f5eb0eb0d2a68d2d86f4c39955b5ab513f0a1.tar.bz2
Merge the receive routines.
Fix error message in web server - socket driver not loaded. Signed-off by: Lee Leahy git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/branches/EADK@12382 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--StdLib/EfiSocketLib/Ip4.c337
-rw-r--r--StdLib/EfiSocketLib/Socket.c412
-rw-r--r--StdLib/EfiSocketLib/Socket.h60
-rw-r--r--StdLib/EfiSocketLib/Tcp4.c337
-rw-r--r--StdLib/EfiSocketLib/Udp4.c301
-rw-r--r--StdLib/UseSocketDxe/UseSocketDxe.c2
6 files changed, 634 insertions, 815 deletions
diff --git a/StdLib/EfiSocketLib/Ip4.c b/StdLib/EfiSocketLib/Ip4.c
index 51820be..38cea89 100644
--- a/StdLib/EfiSocketLib/Ip4.c
+++ b/StdLib/EfiSocketLib/Ip4.c
@@ -504,12 +504,14 @@ EslIp4PortClosePacketFree (
IN OUT size_t * pRxBytes
)
{
+ EFI_IP4_RECEIVE_DATA * pRxData;
DBG_ENTER ( );
//
// Account for the receive bytes
//
- *pRxBytes -= pPacket->Op.Ip4Rx.pRxData->DataLength;
+ pRxData = pPacket->Op.Ip4Rx.pRxData;
+ *pRxBytes -= pRxData->HeaderLength + pRxData->DataLength;
//
// Return the buffer to the IP4 driver
@@ -580,300 +582,124 @@ EslIp4PortCloseRxStop (
Receive data from a network connection.
This routine attempts to return buffered data to the caller. The
- data is only removed from the normal queue, the message flag
- MSG_OOB is ignored. See the \ref Ip4ReceiveEngine section.
+ data is removed from the urgent queue if the message flag MSG_OOB
+ is specified, otherwise data is removed from the normal queue.
+ See the \ref ReceiveEngine section.
This routine is called by ::EslSocketReceive to handle the network
specific receive operation to support SOCK_RAW sockets.
- @param [in] pSocket Address of an ::ESL_SOCKET structure
-
- @param [in] Flags Message control flags
+ @param [in] pPort Address of an ::ESL_PORT structure.
+ @param [in] pPacket Address of an ::ESL_PACKET structure.
+
+ @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
+
@param [in] BufferLength Length of the the buffer
-
+
@param [in] pBuffer Address of a buffer to receive the data.
-
+
@param [in] pDataLength Number of received data bytes in the buffer.
@param [out] pAddress Network address to receive the remote system address
- @param [in,out] pAddressLength Length of the remote network address structure
+ @param [out] pSkipBytes Address to receive the number of bytes skipped
- @retval EFI_SUCCESS - Socket data successfully received
+ @return Returns the address of the next free byte in the buffer.
-**/
-EFI_STATUS
+ **/
+UINT8 *
EslIp4Receive (
- IN ESL_SOCKET * pSocket,
- IN INT32 Flags,
+ IN ESL_PORT * pPort,
+ IN ESL_PACKET * pPacket,
+ IN BOOLEAN * pbConsumePacket,
IN size_t BufferLength,
IN UINT8 * pBuffer,
OUT size_t * pDataLength,
OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
+ OUT size_t * pSkipBytes
)
{
- socklen_t AddressLength;
- size_t BytesToCopy;
size_t DataBytes;
- UINT32 Fragment;
size_t HeaderBytes;
- in_addr_t IpAddress;
size_t LengthInBytes;
- UINT8 * pData;
- ESL_PACKET * pPacket;
- ESL_PORT * pPort;
struct sockaddr_in * pRemoteAddress;
EFI_IP4_RECEIVE_DATA * pRxData;
- ESL_IP4_CONTEXT * pIp4;
- struct sockaddr_in RemoteAddress;
- EFI_STATUS Status;
DBG_ENTER ( );
//
- // Assume failure
+ // Return the remote system address if requested
//
- Status = EFI_UNSUPPORTED;
- pSocket->errno = ENOTCONN;
+ pRxData = pPacket->Op.Ip4Rx.pRxData;
+ if ( NULL != pAddress ) {
+ //
+ // Build the remote address
+ //
+ DEBUG (( DEBUG_RX,
+ "Getting packet remote address: %d.%d.%d.%d\r\n",
+ pRxData->Header->SourceAddress.Addr[0],
+ pRxData->Header->SourceAddress.Addr[1],
+ pRxData->Header->SourceAddress.Addr[2],
+ pRxData->Header->SourceAddress.Addr[3]));
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ CopyMem ( &pRemoteAddress->sin_addr,
+ &pRxData->Header->SourceAddress.Addr[0],
+ sizeof ( pRemoteAddress->sin_addr ));
+ }
//
- // Verify that the socket is connected
+ // Copy the IP header
+ //
+ HeaderBytes = pRxData->HeaderLength;
+ if ( HeaderBytes > BufferLength ) {
+ HeaderBytes = BufferLength;
+ }
+ DEBUG (( DEBUG_RX,
+ "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",
+ pRxData->Header,
+ pBuffer,
+ HeaderBytes ));
+ CopyMem ( pBuffer, pRxData->Header, HeaderBytes );
+ pBuffer += HeaderBytes;
+ LengthInBytes = HeaderBytes;
+
+ //
+ // Copy the received data
+ //
+ if ( 0 < ( BufferLength - LengthInBytes )) {
+ pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,
+ &pRxData->FragmentTable[0],
+ BufferLength - LengthInBytes,
+ pBuffer,
+ &DataBytes );
+ LengthInBytes += DataBytes;
+ }
+
+ //
+ // Determine if the data is being read
//
- if (( SOCKET_STATE_CONNECTED == pSocket->State )
- || ( PORT_STATE_RX_ERROR == pSocket->State )) {
+ if ( *pbConsumePacket ) {
//
- // Locate the port
+ // Display for the bytes consumed
//
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine if there is any data on the queue
- //
- pIp4 = &pPort->Context.Ip4;
- pPacket = pSocket->pRxPacketListHead;
- if ( NULL != pPacket ) {
- //
- // Validate the return address parameters
- //
- pRxData = pPacket->Op.Ip4Rx.pRxData;
- if (( NULL == pAddress ) || ( NULL != pAddressLength )) {
- //
- // Return the remote system address if requested
- //
- if ( NULL != pAddress ) {
- //
- // Build the remote address
- //
- DEBUG (( DEBUG_RX,
- "Getting packet source address: %d.%d.%d.%d\r\n",
- pRxData->Header->SourceAddress.Addr[0],
- pRxData->Header->SourceAddress.Addr[1],
- pRxData->Header->SourceAddress.Addr[2],
- pRxData->Header->SourceAddress.Addr[3]));
- ZeroMem ( &RemoteAddress, sizeof ( RemoteAddress ));
- RemoteAddress.sin_len = sizeof ( RemoteAddress );
- RemoteAddress.sin_family = AF_INET;
- IpAddress = pRxData->Header->SourceAddress.Addr[3];
- IpAddress <<= 8;
- IpAddress |= pRxData->Header->SourceAddress.Addr[2];
- IpAddress <<= 8;
- IpAddress |= pRxData->Header->SourceAddress.Addr[1];
- IpAddress <<= 8;
- IpAddress |= pRxData->Header->SourceAddress.Addr[0];
- RemoteAddress.sin_addr.s_addr = IpAddress;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port account for 0x%08x bytes\r\n",
+ pPort,
+ LengthInBytes ));
- //
- // Copy the address
- //
- pRemoteAddress = (struct sockaddr_in *)pAddress;
- AddressLength = sizeof ( *pRemoteAddress );
- if ( AddressLength > *pAddressLength ) {
- AddressLength = *pAddressLength;
- }
- CopyMem ( pRemoteAddress,
- &RemoteAddress,
- AddressLength );
-
- //
- // Update the address length
- //
- *pAddressLength = AddressLength;
- }
-
- //
- // Reduce the buffer length if necessary
- //
- DataBytes = pRxData->HeaderLength + pRxData->DataLength;
- if ( DataBytes < BufferLength ) {
- BufferLength = DataBytes;
- }
-
- //
- // Copy the IP header
- //
- LengthInBytes = 0;
- HeaderBytes = pRxData->HeaderLength;
- if ( HeaderBytes > BufferLength ) {
- HeaderBytes = BufferLength;
- }
- DEBUG (( DEBUG_RX,
- "0x%08x: Port copy header 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
- pPort,
- pRxData->Header,
- pBuffer,
- HeaderBytes ));
- CopyMem ( pBuffer, pRxData->Header, HeaderBytes );
- pBuffer += HeaderBytes;
- LengthInBytes += HeaderBytes;
-
- //
- // Copy the received data
- //
- Fragment = 0;
- while ( BufferLength > LengthInBytes ) {
- //
- // Determine the amount of received data
- //
- pData = pRxData->FragmentTable[Fragment].FragmentBuffer;
- BytesToCopy = pRxData->FragmentTable[Fragment].FragmentLength;
- if (( BufferLength - LengthInBytes ) < BytesToCopy ) {
- BytesToCopy = BufferLength - LengthInBytes;
- }
- LengthInBytes += BytesToCopy;
-
- //
- // Move the data into the buffer
- //
- DEBUG (( DEBUG_RX,
- "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
- pPort,
- pPacket,
- pBuffer,
- BytesToCopy ));
- CopyMem ( pBuffer, pData, BytesToCopy );
- pBuffer += BytesToCopy;
- }
-
- //
- // Determine if the data is being read
- //
- if ( 0 == ( Flags & MSG_PEEK )) {
- //
- // Display for the bytes consumed
- //
- DEBUG (( DEBUG_RX,
- "0x%08x: Port account for 0x%08x bytes\r\n",
- pPort,
- BufferLength ));
-
- //
- // All done with this packet
- // Account for any discarded data
- //
- pSocket->RxBytes -= DataBytes;
- if ( 0 != ( DataBytes - BufferLength )) {
- DEBUG (( DEBUG_RX,
- "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
- pPort,
- DataBytes - BufferLength ));
- }
-
- //
- // Remove this packet from the queue
- //
- pSocket->pRxPacketListHead = pPacket->pNext;
- if ( NULL == pSocket->pRxPacketListHead ) {
- pSocket->pRxPacketListTail = NULL;
- }
-
- //
- // Return this packet to the IP4 driver
- //
- gBS->SignalEvent ( pRxData->RecycleSignal );
-
- //
- // Move the packet to the free queue
- //
- pPacket->pNext = pSocket->pRxFree;
- pSocket->pRxFree = pPacket;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port freeing packet 0x%08x\r\n",
- pPort,
- pPacket ));
-
- //
- // Restart this receive operation if necessary
- //
- if (( NULL == pPort->pReceivePending )
- && ( MAX_RX_DATA > pSocket->RxBytes )) {
- EslSocketRxStart ( pPort );
- }
- }
-
- //
- // Return the data length
- //
- *pDataLength = LengthInBytes;
-
- //
- // Successful operation
- //
- Status = EFI_SUCCESS;
- pSocket->errno = 0;
- }
- else {
- //
- // Bad return address pointer and length
- //
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
- }
- }
- else {
- //
- // The queue is empty
- // Determine if it is time to return the receive error
- //
- if ( EFI_ERROR ( pSocket->RxError )) {
- Status = pSocket->RxError;
- switch ( Status ) {
- default:
- pSocket->errno = EIO;
- break;
-
- case EFI_HOST_UNREACHABLE:
- pSocket->errno = EHOSTUNREACH;
- break;
-
- case EFI_NETWORK_UNREACHABLE:
- pSocket->errno = ENETUNREACH;
- break;
-
- case EFI_PORT_UNREACHABLE:
- pSocket->errno = EPROTONOSUPPORT;
- break;
-
- case EFI_PROTOCOL_UNREACHABLE:
- pSocket->errno = ENOPROTOOPT;
- break;
- }
- pSocket->RxError = EFI_SUCCESS;
- }
- else {
- Status = EFI_NOT_READY;
- pSocket->errno = EAGAIN;
- }
- }
- }
+ //
+ // Account for any discarded data
+ //
+ *pSkipBytes = pRxData->HeaderLength + pRxData->DataLength - LengthInBytes;
}
//
- // Return the operation status
+ // Return the data length and the buffer address
//
- DBG_EXIT_STATUS ( Status );
- return Status;
+ *pDataLength = LengthInBytes;
+ DBG_EXIT_HEX ( pBuffer );
+ return pBuffer;
}
@@ -1657,6 +1483,7 @@ CONST ESL_PROTOCOL_API cEslIp4Api = {
sizeof ( struct sockaddr_in ),
AF_INET,
sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
+ FALSE,
NULL, // Accept
NULL, // ConnectPoll
NULL, // ConnectStart
diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c
index cd6d489..cf3c32c 100644
--- a/StdLib/EfiSocketLib/Socket.c
+++ b/StdLib/EfiSocketLib/Socket.c
@@ -1378,6 +1378,87 @@ EslSocketConnect (
/**
+ Copy a fragmented buffer into a destination buffer.
+
+ This support routine copies a fragmented buffer to the caller specified buffer.
+
+ This routine is called by ::EslIp4Receive and ::EslUdp4Receive.
+
+ @param [in] FragmentCount Number of fragments in the table
+
+ @param [in] pFragmentTable Address of an EFI_IP4_FRAGMENT_DATA structure
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @return Returns the address of the next free byte in the buffer.
+
+**/
+UINT8 *
+EslSocketCopyFragmentedBuffer (
+ IN UINT32 FragmentCount,
+ IN EFI_IP4_FRAGMENT_DATA * pFragmentTable,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength
+ )
+{
+ size_t BytesToCopy;
+ UINT32 Fragment;
+ UINT8 * pBufferEnd;
+ UINT8 * pData;
+
+ DBG_ENTER ( );
+
+ //
+ // Validate the IP and UDP structures are identical
+ //
+ ASSERT ( OFFSET_OF ( EFI_IP4_FRAGMENT_DATA, FragmentLength )
+ == OFFSET_OF ( EFI_UDP4_FRAGMENT_DATA, FragmentLength ));
+ ASSERT ( OFFSET_OF ( EFI_IP4_FRAGMENT_DATA, FragmentBuffer )
+ == OFFSET_OF ( EFI_UDP4_FRAGMENT_DATA, FragmentBuffer ));
+
+ //
+ // Copy the received data
+ //
+ Fragment = 0;
+ pBufferEnd = &pBuffer [ BufferLength ];
+ while (( pBufferEnd > pBuffer ) && ( FragmentCount > Fragment )) {
+ //
+ // Determine the amount of received data
+ //
+ pData = pFragmentTable[Fragment].FragmentBuffer;
+ BytesToCopy = pFragmentTable[Fragment].FragmentLength;
+ if (((size_t)( pBufferEnd - pBuffer )) < BytesToCopy ) {
+ BytesToCopy = pBufferEnd - pBuffer;
+ }
+
+ //
+ // Move the data into the buffer
+ //
+ DEBUG (( DEBUG_RX,
+ "0x%08x --> 0x%08x: Copy data 0x%08x bytes\r\n",
+ pData,
+ pBuffer,
+ BytesToCopy ));
+ CopyMem ( pBuffer, pData, BytesToCopy );
+ pBuffer += BytesToCopy;
+ Fragment += 1;
+ }
+
+ //
+ // Return the data length and the buffer address
+ //
+ *pDataLength = BufferLength - ( pBufferEnd - pBuffer );
+ DBG_EXIT_HEX ( pBuffer );
+ return pBuffer;
+}
+
+
+/**
Get the local address.
This routine calls the network specific layer to get the network
@@ -3650,7 +3731,22 @@ EslSocketReceive (
IN int * pErrno
)
{
+ union {
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ } Addr;
+ socklen_t AddressLength;
+ BOOLEAN bConsumePacket;
+ size_t DataLength;
+ ESL_PACKET * pNextPacket;
+ ESL_PACKET * pPacket;
+ ESL_PORT * pPort;
+ ESL_PACKET ** ppQueueHead;
+ ESL_PACKET ** ppQueueTail;
+ struct sockaddr * pRemoteAddress;
+ size_t * pRxDataBytes;
ESL_SOCKET * pSocket;
+ size_t SkipBytes;
EFI_STATUS Status;
EFI_TPL TplPrevious;
@@ -3669,72 +3765,275 @@ EslSocketReceive (
pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
//
- // Return the transmit error if necessary
+ // Validate the return address parameters
//
- if ( EFI_SUCCESS != pSocket->TxError ) {
- pSocket->errno = EIO;
- Status = pSocket->TxError;
- pSocket->TxError = EFI_SUCCESS;
- }
- else {
+ if (( NULL == pAddress ) || ( NULL != pAddressLength )) {
//
- // Verify the socket state
+ // Return the transmit error if necessary
//
- Status = EslSocketIsConfigured ( pSocket );
- if ( !EFI_ERROR ( Status )) {
+ if ( EFI_SUCCESS != pSocket->TxError ) {
+ pSocket->errno = EIO;
+ Status = pSocket->TxError;
+ pSocket->TxError = EFI_SUCCESS;
+ }
+ else {
//
- // Validate the buffer length
+ // Verify the socket state
//
- 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 {
+ Status = EslSocketIsConfigured ( pSocket );
+ if ( !EFI_ERROR ( Status )) {
//
- // Verify the API
+ // Validate the buffer length
//
- if ( NULL == pSocket->pApi->pfnReceive ) {
- Status = EFI_UNSUPPORTED;
- pSocket->errno = ENOTSUP;
+ 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
+ // Verify the API
//
- RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+ if ( NULL == pSocket->pApi->pfnReceive ) {
+ Status = EFI_UNSUPPORTED;
+ pSocket->errno = ENOTSUP;
+ }
+ else {
+ //
+ // Zero the receive address if being returned
+ //
+ pRemoteAddress = NULL;
+ if ( NULL != pAddress ) {
+ pRemoteAddress = (struct sockaddr *)&Addr;
+ ZeroMem ( pRemoteAddress, sizeof ( Addr ));
+ ZeroMem ( pAddress, *pAddressLength );
+ pRemoteAddress->sa_len = (UINT8)pSocket->pApi->AddressLength;
+ pRemoteAddress->sa_family = pSocket->pApi->AddressFamily;
+ }
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
- //
- // Attempt to receive a packet
- //
- Status = pSocket->pApi->pfnReceive ( pSocket,
- Flags,
- BufferLength,
- pBuffer,
- pDataLength,
- pAddress,
- pAddressLength);
+ //
+ // Assume failure
+ //
+ Status = EFI_UNSUPPORTED;
+ pSocket->errno = ENOTCONN;
- //
- // Release the socket layer synchronization
- //
- RESTORE_TPL ( TplPrevious );
+ //
+ // Verify that the socket is connected
+ //
+ if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
+ //
+ // Locate the port
+ //
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Determine the queue head
+ //
+ if ( pSocket->bOobSupported && ( 0 != ( Flags & MSG_OOB ))) {
+ ppQueueHead = &pSocket->pRxOobPacketListHead;
+ ppQueueTail = &pSocket->pRxOobPacketListTail;
+ pRxDataBytes = &pSocket->RxOobBytes;
+ }
+ else {
+ ppQueueHead = &pSocket->pRxPacketListHead;
+ ppQueueTail = &pSocket->pRxPacketListTail;
+ pRxDataBytes = &pSocket->RxBytes;
+ }
+
+ //
+ // Determine if there is any data on the queue
+ //
+ *pDataLength = 0;
+ pPacket = *ppQueueHead;
+ if ( NULL != pPacket ) {
+ //
+ // Copy the received data
+ //
+ do {
+ //
+ // Attempt to receive a packet
+ //
+ SkipBytes = 0;
+ bConsumePacket = (BOOLEAN)( 0 == ( Flags & MSG_PEEK ));
+ pBuffer = pSocket->pApi->pfnReceive ( pPort,
+ pPacket,
+ &bConsumePacket,
+ BufferLength,
+ pBuffer,
+ &DataLength,
+ (struct sockaddr *)&Addr,
+ &SkipBytes );
+ *pDataLength += DataLength;
+ BufferLength -= DataLength;
+
+ //
+ // Determine if the data is being read
+ //
+ pNextPacket = pPacket->pNext;
+ if ( bConsumePacket ) {
+ //
+ // All done with this packet
+ // Account for any discarded data
+ //
+ pSocket->pApi->pfnPortClosePktFree ( pPacket, pRxDataBytes );
+ if ( 0 != SkipBytes ) {
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
+ pPort,
+ SkipBytes ));
+ }
+
+ //
+ // Remove this packet from the queue
+ //
+ *ppQueueHead = pPacket->pNext;
+ if ( NULL == *ppQueueHead ) {
+ *ppQueueTail = NULL;
+ }
+
+ //
+ // Move the packet to the free queue
+ //
+ pPacket->pNext = pSocket->pRxFree;
+ pSocket->pRxFree = pPacket;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port freeing packet 0x%08x\r\n",
+ pPort,
+ pPacket ));
+
+ //
+ // Restart this receive operation if necessary
+ //
+ if (( NULL == pPort->pReceivePending )
+ && ( MAX_RX_DATA > pSocket->RxBytes )) {
+ EslSocketRxStart ( pPort );
+ }
+ }
+
+ //
+ // Get the next packet
+ //
+ pPacket = pNextPacket;
+ } while (( SOCK_STREAM == pSocket->Type )
+ && ( NULL != pPacket )
+ && ( 0 < BufferLength ));
+
+ //
+ // Successful operation
+ //
+ Status = EFI_SUCCESS;
+ pSocket->errno = 0;
+ }
+ else {
+ //
+ // The queue is empty
+ // Determine if it is time to return the receive error
+ //
+ if ( EFI_ERROR ( pSocket->RxError )
+ && ( NULL == pSocket->pRxPacketListHead )
+ && ( NULL == pSocket->pRxOobPacketListHead )) {
+ Status = pSocket->RxError;
+ pSocket->RxError = EFI_SUCCESS;
+ switch ( Status ) {
+ default:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_CONNECTION_FIN:
+ //
+ // 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;
+
+ case EFI_CONNECTION_REFUSED:
+ pSocket->errno = ECONNREFUSED;
+ break;
+
+ case EFI_CONNECTION_RESET:
+ pSocket->errno = ECONNRESET;
+ break;
+
+ case EFI_HOST_UNREACHABLE:
+ pSocket->errno = EHOSTUNREACH;
+ break;
+
+ case EFI_NETWORK_UNREACHABLE:
+ pSocket->errno = ENETUNREACH;
+ break;
+
+ case EFI_PORT_UNREACHABLE:
+ pSocket->errno = EPROTONOSUPPORT;
+ break;
+
+ case EFI_PROTOCOL_UNREACHABLE:
+ pSocket->errno = ENOPROTOOPT;
+ break;
+ }
+ }
+ else {
+ Status = EFI_NOT_READY;
+ pSocket->errno = EAGAIN;
+ }
+ }
+ }
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ if (( !EFI_ERROR ( Status )) && ( NULL != pAddress )) {
+ //
+ // Return the remote address if requested, truncate if necessary
+ //
+ AddressLength = pRemoteAddress->sa_len;
+ if ( AddressLength > *pAddressLength ) {
+ AddressLength = *pAddressLength;
+ }
+ CopyMem ( pAddress, &Addr, AddressLength );
+
+ //
+ // Update the address length
+ //
+ *pAddressLength = pRemoteAddress->sa_len;
+ }
+ }
}
}
}
+
+
+ }
+ else {
+ //
+ // Bad return address pointer and length
+ //
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
}
}
@@ -3800,7 +4099,7 @@ EslSocketRxComplete (
pPort->pReceivePending = NULL;
//
- // Account for the received data
+ // Determine the queue to use
//
pSocket = pPort->pSocket;
if ( bUrgent && ( !pSocket->bOobInLine )) {
@@ -3813,7 +4112,6 @@ EslSocketRxComplete (
ppQueueTail = &pSocket->pRxPacketListTail;
pRxBytes = &pSocket->RxBytes;
}
- *pRxBytes += LengthInBytes;
//
// Determine if this receive was successful
@@ -3822,6 +4120,11 @@ EslSocketRxComplete (
&& ( PORT_STATE_CLOSE_STARTED > pPort->State )
&& ( !pSocket->bRxDisable )) {
//
+ // Account for the received data
+ //
+ *pRxBytes += LengthInBytes;
+
+ //
// Set the buffer size and address
//
pPacket->Op.Tcp4Rx.pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;
@@ -3876,7 +4179,10 @@ EslSocketRxComplete (
//
// Account for the receive bytes and release the driver's buffer
//
- pSocket->pApi->pfnPortClosePktFree ( pPacket, pRxBytes );
+ if ( !EFI_ERROR ( Status )) {
+ *pRxBytes += LengthInBytes;
+ pSocket->pApi->pfnPortClosePktFree ( pPacket, pRxBytes );
+ }
//
// Receive error, free the packet save the error
diff --git a/StdLib/EfiSocketLib/Socket.h b/StdLib/EfiSocketLib/Socket.h
index 9dafc54..9dfb087 100644
--- a/StdLib/EfiSocketLib/Socket.h
+++ b/StdLib/EfiSocketLib/Socket.h
@@ -634,9 +634,19 @@ VOID
/**
Receive data from a network connection.
- @param [in] pSocket Address of a ESL_SOCKET structure
+ This routine attempts to return buffered data to the caller. The
+ data is removed from the urgent queue if the message flag MSG_OOB
+ is specified, otherwise data is removed from the normal queue.
+ See the \ref ReceiveEngine section.
+
+ This routine is called by ::EslSocketReceive to handle the network
+ specific receive operation.
+
+ @param [in] pPort Address of an ::ESL_PORT structure.
+
+ @param [in] pPacket Address of an ::ESL_PACKET structure.
- @param [in] Flags Message control flags
+ @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
@param [in] BufferLength Length of the the buffer
@@ -646,21 +656,22 @@ VOID
@param [out] pAddress Network address to receive the remote system address
- @param [in,out] pAddressLength Length of the remote network address structure
+ @param [out] pSkipBytes Address to receive the number of bytes skipped
- @retval EFI_SUCCESS - Socket data successfully received
+ @return Returns the address of the next free byte in the buffer.
-**/
+ **/
typedef
-EFI_STATUS
+UINT8 *
(* PFN_API_RECEIVE) (
- IN ESL_SOCKET * pSocket,
- IN INT32 Flags,
+ IN ESL_PORT * pPort,
+ IN ESL_PACKET * pPacket,
+ IN BOOLEAN * pbConsumePacket,
IN size_t BufferLength,
IN UINT8 * pBuffer,
OUT size_t * pDataLength,
OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
+ OUT size_t * pSkipBytes
);
/**
@@ -801,6 +812,7 @@ typedef struct {
socklen_t AddressLength; ///< Address length in bytes
sa_family_t AddressFamily; ///< Address family
UINTN RxPacketBytes; ///< Length of the RX packet allocation
+ BOOLEAN bOobSupported; ///< TRUE if out-of-band messages are supported
PFN_API_ACCEPT pfnAccept; ///< Accept a network connection
PFN_API_CONNECT_POLL pfnConnectPoll; ///< Poll for connection complete
PFN_API_CONNECT_START pfnConnectStart; ///< Start the connection to a remote system
@@ -851,6 +863,7 @@ typedef struct _ESL_SOCKET {
//
// Socket options
//
+ BOOLEAN bOobSupported; ///< TRUE if out-of-band messages are supported
BOOLEAN bOobInLine; ///< TRUE if out-of-band messages are to be received inline with normal data
BOOLEAN bIncludeHeader; ///< TRUE if including the IP header
@@ -997,6 +1010,35 @@ EslSocketAllocate (
);
/**
+ Copy a fragmented buffer into a destination buffer.
+
+ This support routine copies a fragmented buffer to the caller specified buffer.
+
+ This routine is called by ::EslIp4Receive and ::EslUdp4Receive.
+
+ @param [in] FragmentCount Number of fragments in the table
+
+ @param [in] pFragmentTable Address of an EFI_IP4_FRAGMENT_DATA structure
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @return Returns the address of the next free byte in the buffer.
+
+**/
+UINT8 *
+EslSocketCopyFragmentedBuffer (
+ IN UINT32 FragmentCount,
+ IN EFI_IP4_FRAGMENT_DATA * pFragmentTable,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength
+ );
+
+/**
Free the ESL_IO_MGMT event and structure
This support routine walks the free list to close the event in
diff --git a/StdLib/EfiSocketLib/Tcp4.c b/StdLib/EfiSocketLib/Tcp4.c
index 13ebb5b..e8181b4 100644
--- a/StdLib/EfiSocketLib/Tcp4.c
+++ b/StdLib/EfiSocketLib/Tcp4.c
@@ -1467,15 +1467,17 @@ EslTcp4PortCloseRxStop (
This routine attempts to return buffered data to the caller. The
data is removed from the urgent queue if the message flag MSG_OOB
is specified, otherwise data is removed from the normal queue.
- See the \ref Tcp4ReceiveEngine section.
+ See the \ref ReceiveEngine section.
This routine is called by ::EslSocketReceive to handle the network
specific receive operation to support SOCK_STREAM and SOCK_SEQPACKET
sockets.
- @param [in] pSocket Address of an ::ESL_SOCKET structure.
+ @param [in] pPort Address of an ::ESL_PORT structure.
+
+ @param [in] pPacket Address of an ::ESL_PACKET structure.
- @param [in] Flags Message control flags
+ @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
@param [in] BufferLength Length of the the buffer
@@ -1485,292 +1487,110 @@ EslTcp4PortCloseRxStop (
@param [out] pAddress Network address to receive the remote system address
- @param [in,out] pAddressLength Length of the remote network address structure
+ @param [out] pSkipBytes Address to receive the number of bytes skipped
- @retval EFI_SUCCESS - Socket data successfully received
+ @return Returns the address of the next free byte in the buffer.
**/
-EFI_STATUS
+UINT8 *
EslTcp4Receive (
- IN ESL_SOCKET * pSocket,
- IN INT32 Flags,
+ IN ESL_PORT * pPort,
+ IN ESL_PACKET * pPacket,
+ IN BOOLEAN * pbConsumePacket,
IN size_t BufferLength,
IN UINT8 * pBuffer,
OUT size_t * pDataLength,
OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
+ OUT size_t * pSkipBytes
)
{
- socklen_t AddressLength;
- size_t BytesToCopy;
- in_addr_t IpAddress;
- size_t LengthInBytes;
- ESL_PACKET * pPacket;
- ESL_PORT * pPort;
- ESL_PACKET ** ppQueueHead;
- ESL_PACKET ** ppQueueTail;
+ size_t DataLength;
struct sockaddr_in * pRemoteAddress;
- size_t * pRxDataBytes;
ESL_TCP4_CONTEXT * pTcp4;
- struct sockaddr_in RemoteAddress;
- EFI_STATUS Status;
DBG_ENTER ( );
//
- // Assume failure
+ // Return the remote system address if requested
//
- Status = EFI_UNSUPPORTED;
- pSocket->errno = ENOTCONN;
+ if ( NULL != pAddress ) {
+ //
+ // Build the remote address
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ DEBUG (( DEBUG_RX,
+ "Getting packet remote address: %d.%d.%d.%d:%d\r\n",
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
+ pTcp4->ConfigData.AccessPoint.RemotePort ));
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ CopyMem ( &pRemoteAddress->sin_addr,
+ &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ sizeof ( pRemoteAddress->sin_addr ));
+ pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
+ }
//
- // Verify that the socket is connected
+ // Determine the amount of received data
+ //
+ DataLength = pPacket->Op.Tcp4Rx.ValidBytes;
+ if ( BufferLength < DataLength ) {
+ DataLength = BufferLength;
+ }
+
+ //
+ // Move the data into the buffer
+ //
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
+ pPort,
+ pPacket,
+ pBuffer,
+ DataLength ));
+ CopyMem ( pBuffer, pPacket->Op.Tcp4Rx.pBuffer, DataLength );
+
//
- if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
+ // Determine if the data is being read
+ //
+ if ( *pbConsumePacket ) {
//
- // Locate the port
+ // Account for the bytes consumed
//
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
+ pPacket->Op.Tcp4Rx.pBuffer += DataLength;
+ pPacket->Op.Tcp4Rx.ValidBytes -= DataLength;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port account for 0x%08x bytes\r\n",
+ pPort,
+ DataLength ));
+
+ //
+ // Determine if the entire packet was consumed
+ //
+ if (( 0 == pPacket->Op.Tcp4Rx.ValidBytes )
+ || ( SOCK_STREAM != pPort->pSocket->Type )) {
//
- // Determine the queue head
+ // All done with this packet
+ // Account for any discarded data
//
- pTcp4 = &pPort->Context.Tcp4;
- if ( 0 != ( Flags & MSG_OOB )) {
- ppQueueHead = &pSocket->pRxOobPacketListHead;
- ppQueueTail = &pSocket->pRxOobPacketListTail;
- pRxDataBytes = &pSocket->RxOobBytes;
- }
- else {
- ppQueueHead = &pSocket->pRxPacketListHead;
- ppQueueTail = &pSocket->pRxPacketListTail;
- pRxDataBytes = &pSocket->RxBytes;
- }
-
+ *pSkipBytes = pPacket->Op.Tcp4Rx.ValidBytes;
+ }
+ else
+ {
//
- // Determine if there is any data on the queue
+ // More data to consume later
//
- pPacket = *ppQueueHead;
- if ( NULL != pPacket ) {
- //
- // Validate the return address parameters
- //
- if (( NULL == pAddress ) || ( NULL != pAddressLength )) {
- //
- // Return the remote system address if requested
- //
- if ( NULL != pAddress ) {
- //
- // Build the remote address
- //
- ZeroMem ( &RemoteAddress, sizeof ( RemoteAddress ));
- RemoteAddress.sin_len = sizeof ( RemoteAddress );
- RemoteAddress.sin_family = AF_INET;
- IpAddress = pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3];
- IpAddress <<= 8;
- IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2];
- IpAddress <<= 8;
- IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1];
- IpAddress <<= 8;
- IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0];
- RemoteAddress.sin_addr.s_addr = IpAddress;
- RemoteAddress.sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
-
- //
- // Copy the address
- //
- pRemoteAddress = (struct sockaddr_in *)pAddress;
- AddressLength = sizeof ( *pRemoteAddress );
- if ( AddressLength > *pAddressLength ) {
- AddressLength = *pAddressLength;
- }
- CopyMem ( pRemoteAddress,
- &RemoteAddress,
- AddressLength );
-
- //
- // Update the address length
- //
- *pAddressLength = AddressLength;
- }
-
- //
- // Copy the received data
- //
- LengthInBytes = 0;
- do {
- //
- // Determine the amount of received data
- //
- BytesToCopy = pPacket->Op.Tcp4Rx.ValidBytes;
- if (( BufferLength - LengthInBytes ) < BytesToCopy ) {
- BytesToCopy = BufferLength - LengthInBytes;
- }
- LengthInBytes += BytesToCopy;
-
- //
- // Move the data into the buffer
- //
- DEBUG (( DEBUG_RX,
- "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
- pPort,
- pPacket,
- pBuffer,
- BytesToCopy ));
- CopyMem ( pBuffer, pPacket->Op.Tcp4Rx.pBuffer, BytesToCopy );
-
- //
- // Determine if the data is being read
- //
- if ( 0 == ( Flags & MSG_PEEK )) {
- //
- // Account for the bytes consumed
- //
- pPacket->Op.Tcp4Rx.pBuffer += BytesToCopy;
- pPacket->Op.Tcp4Rx.ValidBytes -= BytesToCopy;
- *pRxDataBytes -= BytesToCopy;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port account for 0x%08x bytes\r\n",
- pPort,
- BytesToCopy ));
-
- //
- // Determine if the entire packet was consumed
- //
- if (( 0 == pPacket->Op.Tcp4Rx.ValidBytes )
- || ( SOCK_STREAM != pSocket->Type )) {
- //
- // All done with this packet
- // Account for any discarded data
- //
- *pRxDataBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
- if ( 0 != pPacket->Op.Tcp4Rx.ValidBytes ) {
- DEBUG (( DEBUG_RX,
- "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
- pPort,
- pPacket->Op.Tcp4Rx.ValidBytes ));
- }
-
- //
- // Remove this packet from the queue
- //
- *ppQueueHead = pPacket->pNext;
- if ( NULL == *ppQueueHead ) {
- *ppQueueTail = NULL;
- }
-
- //
- // Move the packet to the free queue
- //
- pPacket->pNext = pSocket->pRxFree;
- pSocket->pRxFree = pPacket;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port freeing packet 0x%08x\r\n",
- pPort,
- pPacket ));
-
- //
- // Restart this receive operation if necessary
- //
- if (( NULL == pPort->pReceivePending )
- && ( MAX_RX_DATA > pSocket->RxBytes )) {
- EslSocketRxStart ( pPort );
- }
- }
- }
-
- //
- // Get the next packet
- //
- pPacket = *ppQueueHead;
- } while (( SOCK_STREAM == pSocket->Type )
- && ( NULL != pPacket )
- && ( 0 == ( Flags & MSG_PEEK ))
- && ( BufferLength > LengthInBytes ));
-
- //
- // Return the data length
- //
- *pDataLength = LengthInBytes;
-
- //
- // Successful operation
- //
- Status = EFI_SUCCESS;
- pSocket->errno = 0;
- }
- else {
- //
- // Bad return address pointer and length
- //
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
- }
- }
- else {
- //
- // The queue is empty
- // Determine if it is time to return the receive error
- //
- if ( EFI_ERROR ( pSocket->RxError )
- && ( NULL == pSocket->pRxPacketListHead )
- && ( NULL == pSocket->pRxOobPacketListHead )) {
- Status = pSocket->RxError;
- pSocket->RxError = EFI_SUCCESS;
- switch ( Status ) {
- default:
- pSocket->errno = EIO;
- break;
-
- case EFI_CONNECTION_FIN:
- //
- // 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;
-
- case EFI_CONNECTION_REFUSED:
- pSocket->errno = ECONNREFUSED;
- break;
-
- case EFI_CONNECTION_RESET:
- pSocket->errno = ECONNRESET;
- break;
-
- case EFI_HOST_UNREACHABLE:
- pSocket->errno = EHOSTUNREACH;
- break;
-
- case EFI_NETWORK_UNREACHABLE:
- pSocket->errno = ENETUNREACH;
- break;
-
- case EFI_PORT_UNREACHABLE:
- pSocket->errno = EPROTONOSUPPORT;
- break;
-
- case EFI_PROTOCOL_UNREACHABLE:
- pSocket->errno = ENOPROTOOPT;
- break;
- }
- }
- else {
- Status = EFI_NOT_READY;
- pSocket->errno = EAGAIN;
- }
- }
+ *pbConsumePacket = FALSE;
}
}
//
- // Return the operation status
+ // Return the data length and the buffer address
//
- DBG_EXIT_STATUS ( Status );
- return Status;
+ *pDataLength = DataLength;
+ DBG_EXIT_HEX ( pBuffer );
+ return pBuffer;
}
@@ -2422,6 +2242,7 @@ CONST ESL_PROTOCOL_API cEslTcp4Api = {
sizeof ( struct sockaddr_in ),
AF_INET,
sizeof (((ESL_PACKET *)0 )->Op.Tcp4Rx ),
+ FALSE,
EslTcp4Accept,
EslTcp4ConnectPoll,
EslTcp4ConnectStart,
diff --git a/StdLib/EfiSocketLib/Udp4.c b/StdLib/EfiSocketLib/Udp4.c
index 4c11bf6..058ffb2 100644
--- a/StdLib/EfiSocketLib/Udp4.c
+++ b/StdLib/EfiSocketLib/Udp4.c
@@ -390,283 +390,105 @@ EslUdp4PortCloseRxStop (
Receive data from a network connection.
This routine attempts to return buffered data to the caller. The
- data is only removed from the normal queue, the message flag
- MSG_OOB is ignored. See the \ref Udp4ReceiveEngine section.
+ data is removed from the urgent queue if the message flag MSG_OOB
+ is specified, otherwise data is removed from the normal queue.
+ See the \ref ReceiveEngine section.
This routine is called by ::EslSocketReceive to handle the network
specific receive operation to support SOCK_DGRAM sockets.
- @param [in] pSocket Address of an ::ESL_SOCKET structure
-
- @param [in] Flags Message control flags
+ @param [in] pPort Address of an ::ESL_PORT structure.
+ @param [in] pPacket Address of an ::ESL_PACKET structure.
+
+ @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
+
@param [in] BufferLength Length of the the buffer
-
+
@param [in] pBuffer Address of a buffer to receive the data.
-
+
@param [in] pDataLength Number of received data bytes in the buffer.
@param [out] pAddress Network address to receive the remote system address
- @param [in,out] pAddressLength Length of the remote network address structure
+ @param [out] pSkipBytes Address to receive the number of bytes skipped
- @retval EFI_SUCCESS - Socket data successfully received
+ @return Returns the address of the next free byte in the buffer.
-**/
-EFI_STATUS
+ **/
+UINT8 *
EslUdp4Receive (
- IN ESL_SOCKET * pSocket,
- IN INT32 Flags,
+ IN ESL_PORT * pPort,
+ IN ESL_PACKET * pPacket,
+ IN BOOLEAN * pbConsumePacket,
IN size_t BufferLength,
IN UINT8 * pBuffer,
OUT size_t * pDataLength,
OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
+ OUT size_t * pSkipBytes
)
{
- socklen_t AddressLength;
- size_t BytesToCopy;
size_t DataBytes;
- UINT32 Fragment;
- in_addr_t IpAddress;
- size_t LengthInBytes;
- UINT8 * pData;
- ESL_PACKET * pPacket;
- ESL_PORT * pPort;
struct sockaddr_in * pRemoteAddress;
EFI_UDP4_RECEIVE_DATA * pRxData;
- ESL_UDP4_CONTEXT * pUdp4;
- struct sockaddr_in RemoteAddress;
- EFI_STATUS Status;
DBG_ENTER ( );
+ pRxData = pPacket->Op.Udp4Rx.pRxData;
//
- // Assume failure
+ // Return the remote system address if requested
//
- Status = EFI_UNSUPPORTED;
- pSocket->errno = ENOTCONN;
+ if ( NULL != pAddress ) {
+ //
+ // Build the remote address
+ //
+ DEBUG (( DEBUG_RX,
+ "Getting packet remote address: %d.%d.%d.%d:%d\r\n",
+ pRxData->UdpSession.SourceAddress.Addr[0],
+ pRxData->UdpSession.SourceAddress.Addr[1],
+ pRxData->UdpSession.SourceAddress.Addr[2],
+ pRxData->UdpSession.SourceAddress.Addr[3],
+ pRxData->UdpSession.SourcePort ));
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ CopyMem ( &pRemoteAddress->sin_addr,
+ &pRxData->UdpSession.SourceAddress.Addr[0],
+ sizeof ( pRemoteAddress->sin_addr ));
+ pRemoteAddress->sin_port = SwapBytes16 ( pRxData->UdpSession.SourcePort );
+ }
//
- // Verify that the socket is connected
+ // Copy the received data
//
- if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
+ pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,
+ (EFI_IP4_FRAGMENT_DATA *)&pRxData->FragmentTable[0],
+ BufferLength,
+ pBuffer,
+ &DataBytes );
+
+ //
+ // Determine if the data is being read
+ //
+ if ( *pbConsumePacket ) {
//
- // Locate the port
+ // Display for the bytes consumed
//
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine if there is any data on the queue
- //
- pUdp4 = &pPort->Context.Udp4;
- pPacket = pSocket->pRxPacketListHead;
- if ( NULL != pPacket ) {
- //
- // Validate the return address parameters
- //
- pRxData = pPacket->Op.Udp4Rx.pRxData;
- if (( NULL == pAddress ) || ( NULL != pAddressLength )) {
- //
- // Return the remote system address if requested
- //
- if ( NULL != pAddress ) {
- //
- // Build the remote address
- //
- DEBUG (( DEBUG_RX,
- "Getting packet source address: %d.%d.%d.%d:%d\r\n",
- pRxData->UdpSession.SourceAddress.Addr[0],
- pRxData->UdpSession.SourceAddress.Addr[1],
- pRxData->UdpSession.SourceAddress.Addr[2],
- pRxData->UdpSession.SourceAddress.Addr[3],
- pRxData->UdpSession.SourcePort ));
- ZeroMem ( &RemoteAddress, sizeof ( RemoteAddress ));
- RemoteAddress.sin_len = sizeof ( RemoteAddress );
- RemoteAddress.sin_family = AF_INET;
- IpAddress = pRxData->UdpSession.SourceAddress.Addr[3];
- IpAddress <<= 8;
- IpAddress |= pRxData->UdpSession.SourceAddress.Addr[2];
- IpAddress <<= 8;
- IpAddress |= pRxData->UdpSession.SourceAddress.Addr[1];
- IpAddress <<= 8;
- IpAddress |= pRxData->UdpSession.SourceAddress.Addr[0];
- RemoteAddress.sin_addr.s_addr = IpAddress;
- RemoteAddress.sin_port = SwapBytes16 ( pRxData->UdpSession.SourcePort );
-
- //
- // Copy the address
- //
- pRemoteAddress = (struct sockaddr_in *)pAddress;
- AddressLength = sizeof ( *pRemoteAddress );
- if ( AddressLength > *pAddressLength ) {
- AddressLength = *pAddressLength;
- }
- CopyMem ( pRemoteAddress,
- &RemoteAddress,
- AddressLength );
-
- //
- // Update the address length
- //
- *pAddressLength = AddressLength;
- }
-
- //
- // Reduce the buffer length if necessary
- //
- DataBytes = pRxData->DataLength;
- if ( DataBytes < BufferLength ) {
- BufferLength = DataBytes;
- }
-
- //
- // Copy the received data
- //
- LengthInBytes = 0;
- Fragment = 0;
- while ( BufferLength > LengthInBytes ) {
- //
- // Determine the amount of received data
- //
- pData = pRxData->FragmentTable[Fragment].FragmentBuffer;
- BytesToCopy = pRxData->FragmentTable[Fragment].FragmentLength;
- if (( BufferLength - LengthInBytes ) < BytesToCopy ) {
- BytesToCopy = BufferLength - LengthInBytes;
- }
- LengthInBytes += BytesToCopy;
-
- //
- // Move the data into the buffer
- //
- DEBUG (( DEBUG_RX,
- "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
- pPort,
- pPacket,
- pBuffer,
- BytesToCopy ));
- CopyMem ( pBuffer, pData, BytesToCopy );
- pBuffer += BytesToCopy;
- }
-
- //
- // Determine if the data is being read
- //
- if ( 0 == ( Flags & MSG_PEEK )) {
- //
- // Display for the bytes consumed
- //
- DEBUG (( DEBUG_RX,
- "0x%08x: Port account for 0x%08x bytes\r\n",
- pPort,
- BufferLength ));
-
- //
- // All done with this packet
- // Account for any discarded data
- //
- pSocket->RxBytes -= DataBytes;
- if ( 0 != ( DataBytes - BufferLength )) {
- DEBUG (( DEBUG_RX,
- "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
- pPort,
- DataBytes - BufferLength ));
- }
-
- //
- // Remove this packet from the queue
- //
- pSocket->pRxPacketListHead = pPacket->pNext;
- if ( NULL == pSocket->pRxPacketListHead ) {
- pSocket->pRxPacketListTail = NULL;
- }
-
- //
- // Return this packet to the UDP4 driver
- //
- gBS->SignalEvent ( pRxData->RecycleSignal );
-
- //
- // Move the packet to the free queue
- //
- pPacket->pNext = pSocket->pRxFree;
- pSocket->pRxFree = pPacket;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port freeing packet 0x%08x\r\n",
- pPort,
- pPacket ));
-
- //
- // Restart this receive operation if necessary
- //
- if (( NULL == pPort->pReceivePending )
- && ( MAX_RX_DATA > pSocket->RxBytes )) {
- EslSocketRxStart ( pPort );
- }
- }
-
- //
- // Return the data length
- //
- *pDataLength = LengthInBytes;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port account for 0x%08x bytes\r\n",
+ pPort,
+ DataBytes ));
- //
- // Successful operation
- //
- Status = EFI_SUCCESS;
- pSocket->errno = 0;
- }
- else {
- //
- // Bad return address pointer and length
- //
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
- }
- }
- else {
- //
- // The queue is empty
- // Determine if it is time to return the receive error
- //
- if ( EFI_ERROR ( pSocket->RxError )) {
- Status = pSocket->RxError;
- switch ( Status ) {
- default:
- pSocket->errno = EIO;
- break;
-
- case EFI_HOST_UNREACHABLE:
- pSocket->errno = EHOSTUNREACH;
- break;
-
- case EFI_NETWORK_UNREACHABLE:
- pSocket->errno = ENETUNREACH;
- break;
-
- case EFI_PORT_UNREACHABLE:
- pSocket->errno = EPROTONOSUPPORT;
- break;
-
- case EFI_PROTOCOL_UNREACHABLE:
- pSocket->errno = ENOPROTOOPT;
- break;
- }
- pSocket->RxError = EFI_SUCCESS;
- }
- else {
- Status = EFI_NOT_READY;
- pSocket->errno = EAGAIN;
- }
- }
- }
+ //
+ // Account for any discarded data
+ //
+ *pSkipBytes = pRxData->DataLength - DataBytes;
}
//
- // Return the operation status
+ // Return the data length and the buffer address
//
- DBG_EXIT_STATUS ( Status );
- return Status;
+ *pDataLength = DataBytes;
+ DBG_EXIT_HEX ( pBuffer );
+ return pBuffer;
}
@@ -1402,6 +1224,7 @@ CONST ESL_PROTOCOL_API cEslUdp4Api = {
sizeof ( struct sockaddr_in ),
AF_INET,
sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),
+ FALSE,
NULL, // Accept
NULL, // ConnectPoll
NULL, // ConnectStart
diff --git a/StdLib/UseSocketDxe/UseSocketDxe.c b/StdLib/UseSocketDxe/UseSocketDxe.c
index 58a1222..6074143 100644
--- a/StdLib/UseSocketDxe/UseSocketDxe.c
+++ b/StdLib/UseSocketDxe/UseSocketDxe.c
@@ -162,7 +162,7 @@ EslServiceGetProtocol (
}
else {
DEBUG (( DEBUG_ERROR,
- "ERROR - No socket service binding protocol, Status: %r\r\n",
+ "ERROR - Socket driver not loaded, Status: %r\r\n",
Status ));
RetVal = ENODEV;
}