diff options
Diffstat (limited to 'StdLib/EfiSocketLib/Udp4.c')
-rw-r--r-- | StdLib/EfiSocketLib/Udp4.c | 2264 |
1 files changed, 456 insertions, 1808 deletions
diff --git a/StdLib/EfiSocketLib/Udp4.c b/StdLib/EfiSocketLib/Udp4.c index 95fc66517a..e1500d3f9f 100644 --- a/StdLib/EfiSocketLib/Udp4.c +++ b/StdLib/EfiSocketLib/Udp4.c @@ -16,633 +16,153 @@ /**
- Bind a name to a socket.
-
- The ::UdpBind4 routine connects a name to a UDP4 stack on the local machine.
-
- The configure call to the UDP4 driver occurs on the first poll, recv, recvfrom,
- send or sentto call. Until then, all changes are made in the local UDP context
- structure.
-
- @param [in] pSocket Address of the socket structure.
-
- @param [in] pSockAddr Address of a sockaddr structure that contains the
- connection point on the local machine. An IPv4 address
- of INADDR_ANY specifies that the connection is made to
- all of the network stacks on the platform. Specifying a
- specific IPv4 address restricts the connection to the
- network stack supporting that address. Specifying zero
- for the port causes the network layer to assign a port
- number from the dynamic range. Specifying a specific
- port number causes the network layer to use that port.
-
- @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
-
- @retval EFI_SUCCESS - Socket successfully created
-
- **/
-EFI_STATUS
-EslUdpBind4 (
- IN DT_SOCKET * pSocket,
- IN const struct sockaddr * pSockAddr,
- IN socklen_t SockAddrLength
- )
-{
- EFI_HANDLE ChildHandle;
- DT_LAYER * pLayer;
- DT_PORT * pPort;
- DT_SERVICE * pService;
- CONST struct sockaddr_in * pIp4Address;
- EFI_SERVICE_BINDING_PROTOCOL * pUdp4Service;
- EFI_STATUS Status;
- EFI_STATUS TempStatus;
-
- DBG_ENTER ( );
-
- //
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Assume success
- //
- pSocket->errno = 0;
- Status = EFI_SUCCESS;
-
- //
- // Validate the address length
- //
- pIp4Address = (CONST struct sockaddr_in *) pSockAddr;
- if ( SockAddrLength >= ( sizeof ( *pIp4Address )
- - sizeof ( pIp4Address->sin_zero ))) {
-
- //
- // Walk the list of services
- //
- pLayer = &mEslLayer;
- pService = pLayer->pUdp4List;
- while ( NULL != pService ) {
-
- //
- // Create the UDP port
- //
- pUdp4Service = pService->pInterface;
- ChildHandle = NULL;
- Status = pUdp4Service->CreateChild ( pUdp4Service,
- &ChildHandle );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_BIND | DEBUG_POOL,
- "0x%08x: Udp4 port handle created\r\n",
- ChildHandle ));
-
- //
- // Open the port
- //
- Status = EslUdpPortAllocate4 ( pSocket,
- pService,
- ChildHandle,
- (UINT8 *) &pIp4Address->sin_addr.s_addr,
- SwapBytes16 ( pIp4Address->sin_port ),
- DEBUG_BIND,
- &pPort );
- }
- else {
- DEBUG (( DEBUG_BIND | DEBUG_POOL,
- "ERROR - Failed to open Udp4 port handle, Status: %r\r\n",
- Status ));
- ChildHandle = NULL;
- }
-
- //
- // Close the port if necessary
- //
- if (( EFI_ERROR ( Status )) && ( NULL != ChildHandle )) {
- TempStatus = pUdp4Service->DestroyChild ( pUdp4Service,
- ChildHandle );
- if ( !EFI_ERROR ( TempStatus )) {
- DEBUG (( DEBUG_BIND | DEBUG_POOL,
- "0x%08x: Udp4 port handle destroyed\r\n",
- ChildHandle ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL,
- "ERROR - Failed to destroy the Udp4 port handle 0x%08x, Status: %r\r\n",
- ChildHandle,
- TempStatus ));
- ASSERT ( EFI_SUCCESS == TempStatus );
- }
- }
-
- //
- // Set the next service
- //
- pService = pService->pNext;
- }
-
- //
- // Verify that at least one network connection was found
- //
- if ( NULL == pSocket->pPortList ) {
- DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,
- "Socket address %d.%d.%d.%d (0x%08x) is not available!\r\n",
- ( pIp4Address->sin_addr.s_addr >> 24 ) & 0xff,
- ( pIp4Address->sin_addr.s_addr >> 16 ) & 0xff,
- ( pIp4Address->sin_addr.s_addr >> 8 ) & 0xff,
- pIp4Address->sin_addr.s_addr & 0xff,
- pIp4Address->sin_addr.s_addr ));
- pSocket->errno = EADDRNOTAVAIL;
- Status = EFI_INVALID_PARAMETER;
- }
- }
- else {
- DEBUG (( DEBUG_BIND,
- "ERROR - Invalid Udp4 address length: %d\r\n",
- SockAddrLength ));
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
+ Get the local socket address
-/**
- Initialize the UDP4 service.
+ This routine returns the IPv4 address and UDP port number associated
+ with the local socket.
- This routine initializes the UDP4 service after its service binding
- protocol was located on a controller.
+ This routine is called by ::EslSocketGetLocalAddress to determine the
+ network address for the SOCK_DGRAM socket.
- @param [in] pService DT_SERVICE structure address
+ @param [in] pPort Address of an ::ESL_PORT structure.
- @retval EFI_SUCCESS The service was properly initialized
- @retval other A failure occurred during the service initialization
+ @param [out] pSockAddr Network address to receive the local system address
**/
-EFI_STATUS
-EFIAPI
-EslUdpInitialize4 (
- IN DT_SERVICE * pService
+VOID
+EslUdp4LocalAddressGet (
+ IN ESL_PORT * pPort,
+ OUT struct sockaddr * pSockAddr
)
{
- DT_LAYER * pLayer;
- EFI_STATUS Status;
+ struct sockaddr_in * pLocalAddress;
+ ESL_UDP4_CONTEXT * pUdp4;
DBG_ENTER ( );
//
- // Identify the service
- //
- pService->NetworkType = NETWORK_TYPE_UDP4;
-
- //
- // Connect this service to the service list
- //
- pLayer = &mEslLayer;
- pService->pNext = pLayer->pUdp4List;
- pLayer->pUdp4List = pService;
-
+ // Return the local address
//
- // Assume the list is empty
- //
- Status = EFI_SUCCESS;
+ pUdp4 = &pPort->Context.Udp4;
+ pLocalAddress = (struct sockaddr_in *)pSockAddr;
+ pLocalAddress->sin_family = AF_INET;
+ pLocalAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.StationPort );
+ CopyMem ( &pLocalAddress->sin_addr,
+ &pUdp4->ConfigData.StationAddress.Addr[0],
+ sizeof ( pLocalAddress->sin_addr ));
- //
- // Return the initialization status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
+ DBG_EXIT ( );
}
/**
- Allocate and initialize a DT_PORT structure.
+ Set the local port address.
- @param [in] pSocket Address of the socket structure.
- @param [in] pService Address of the DT_SERVICE structure.
- @param [in] ChildHandle Udp4 child handle
- @param [in] pIpAddress Buffer containing IP4 network address of the local host
- @param [in] PortNumber Udp4 port number
- @param [in] DebugFlags Flags for debug messages
- @param [out] ppPort Buffer to receive new DT_PORT structure address
+ This routine sets the local port address.
- @retval EFI_SUCCESS - Socket successfully created
+ This support routine is called by ::EslSocketPortAllocate.
+
+ @param [in] pPort Address of an ESL_PORT structure
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] bBindTest TRUE = run bind testing
+
+ @retval EFI_SUCCESS The operation was successful
**/
EFI_STATUS
-EslUdpPortAllocate4 (
- IN DT_SOCKET * pSocket,
- IN DT_SERVICE * pService,
- IN EFI_HANDLE ChildHandle,
- IN CONST UINT8 * pIpAddress,
- IN UINT16 PortNumber,
- IN UINTN DebugFlags,
- OUT DT_PORT ** ppPort
+EslUdp4LocalAddressSet (
+ IN ESL_PORT * pPort,
+ IN CONST struct sockaddr * pSockAddr,
+ IN BOOLEAN bBindTest
)
{
- UINTN LengthInBytes;
EFI_UDP4_CONFIG_DATA * pConfig;
- DT_LAYER * pLayer;
- DT_PORT * pPort;
- DT_UDP4_CONTEXT * pUdp4;
+ CONST struct sockaddr_in * pIpAddress;
+ CONST UINT8 * pIpv4Address;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Use for/break instead of goto
- for ( ; ; ) {
- //
- // Allocate a port structure
- //
- pLayer = &mEslLayer;
- LengthInBytes = sizeof ( *pPort );
- Status = gBS->AllocatePool ( EfiRuntimeServicesData,
- LengthInBytes,
- (VOID **)&pPort );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,
- "ERROR - Failed to allocate the port structure, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- pPort = NULL;
- break;
- }
- DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
- "0x%08x: Allocate pPort, %d bytes\r\n",
- pPort,
- LengthInBytes ));
-
- //
- // Initialize the port
- //
- ZeroMem ( pPort, LengthInBytes );
- pPort->Signature = PORT_SIGNATURE;
- pPort->pService = pService;
- pPort->pSocket = pSocket;
- pPort->pfnCloseStart = EslUdpPortCloseStart4;
- pPort->DebugFlags = DebugFlags;
-
+ // Validate the address
+ //
+ pIpAddress = (struct sockaddr_in *)pSockAddr;
+ if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {
//
- // Allocate the receive event
+ // The local address must not be the broadcast address
//
- pUdp4 = &pPort->Context.Udp4;
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslUdpRxComplete4,
- pPort,
- &pUdp4->RxToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the receive event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_RX | DEBUG_POOL,
- "0x%08x: Created receive event\r\n",
- pUdp4->RxToken.Event ));
-
+ Status = EFI_INVALID_PARAMETER;
+ pPort->pSocket->errno = EADDRNOTAVAIL;
+ }
+ else {
//
- // Allocate the transmit event
+ // Set the local address
//
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslUdpTxComplete4,
- pPort,
- &pUdp4->TxToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the transmit event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
- "0x%08x: Created transmit event\r\n",
- pUdp4->TxToken.Event ));
+ pIpAddress = (struct sockaddr_in *)pSockAddr;
+ pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;
+ pConfig = &pPort->Context.Udp4.ConfigData;
+ pConfig->StationAddress.Addr[0] = pIpv4Address[0];
+ pConfig->StationAddress.Addr[1] = pIpv4Address[1];
+ pConfig->StationAddress.Addr[2] = pIpv4Address[2];
+ pConfig->StationAddress.Addr[3] = pIpv4Address[3];
//
- // Open the port protocol
+ // Determine if the default address is used
//
- Status = gBS->OpenProtocol (
- ChildHandle,
- &gEfiUdp4ProtocolGuid,
- (VOID **) &pUdp4->pProtocol,
- pLayer->ImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to open gEfiUdp4ProtocolGuid on controller 0x%08x\r\n",
- pUdp4->Handle ));
- pSocket->errno = EEXIST;
- break;
- }
- DEBUG (( DebugFlags,
- "0x%08x: gEfiUdp4ProtocolGuid opened on controller 0x%08x\r\n",
- pUdp4->pProtocol,
- ChildHandle ));
-
+ pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );
+
//
- // Set the port address
+ // Set the subnet mask
//
- pUdp4->Handle = ChildHandle;
- pConfig = &pPort->Context.Udp4.ConfigData;
- pConfig->StationPort = PortNumber;
- if (( 0 == pIpAddress[0])
- && ( 0 == pIpAddress[1])
- && ( 0 == pIpAddress[2])
- && ( 0 == pIpAddress[3])) {
- pConfig->UseDefaultAddress = TRUE;
+ if ( pConfig->UseDefaultAddress ) {
+ pConfig->SubnetMask.Addr[0] = 0;
+ pConfig->SubnetMask.Addr[1] = 0;
+ pConfig->SubnetMask.Addr[2] = 0;
+ pConfig->SubnetMask.Addr[3] = 0;
}
else {
- pConfig->StationAddress.Addr[0] = pIpAddress[0];
- pConfig->StationAddress.Addr[1] = pIpAddress[1];
- pConfig->StationAddress.Addr[2] = pIpAddress[2];
- pConfig->StationAddress.Addr[3] = pIpAddress[3];
pConfig->SubnetMask.Addr[0] = 0xff;
pConfig->SubnetMask.Addr[1] = 0xff;
pConfig->SubnetMask.Addr[2] = 0xff;
pConfig->SubnetMask.Addr[3] = 0xff;
}
- pConfig->TimeToLive = 255;
- pConfig->AcceptAnyPort = FALSE;
- pConfig->AcceptBroadcast = FALSE;
- pConfig->AcceptPromiscuous = FALSE;
- pConfig->AllowDuplicatePort = TRUE;
- pConfig->DoNotFragment = TRUE;
-
- //
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Add this port to the socket
- //
- pPort->pLinkSocket = pSocket->pPortList;
- pSocket->pPortList = pPort;
- DEBUG (( DebugFlags,
- "0x%08x: Socket adding port: 0x%08x\r\n",
- pSocket,
- pPort ));
-
- //
- // Add this port to the service
- //
- pPort->pLinkService = pService->pPortList;
- pService->pPortList = pPort;
-
- //
- // Return the port
- //
- *ppPort = pPort;
- break;
- }
-
- //
- // Clean up after the error if necessary
- //
- if (( EFI_ERROR ( Status )) && ( NULL != pPort )) {
- //
- // Close the port
- //
- EslUdpPortClose4 ( pPort );
- }
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Close a UDP4 port.
-
- This routine releases the resources allocated by
- ::UdpPortAllocate4().
-
- @param [in] pPort Address of the port structure.
-
- @retval EFI_SUCCESS The port is closed
- @retval other Port close error
-
-**/
-EFI_STATUS
-EslUdpPortClose4 (
- IN DT_PORT * pPort
- )
-{
- UINTN DebugFlags;
- DT_LAYER * pLayer;
- DT_PACKET * pPacket;
- DT_PORT * pPreviousPort;
- DT_SERVICE * pService;
- DT_SOCKET * pSocket;
- EFI_SERVICE_BINDING_PROTOCOL * pUdp4Service;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
- pSocket = pPort->pSocket;
- pSocket->errno = 0;
- //
- // Locate the port in the socket list
- //
- pLayer = &mEslLayer;
- DebugFlags = pPort->DebugFlags;
- pPreviousPort = pSocket->pPortList;
- if ( pPreviousPort == pPort ) {
- //
- // Remove this port from the head of the socket list
- //
- pSocket->pPortList = pPort->pLinkSocket;
- }
- else {
//
- // Locate the port in the middle of the socket list
+ // Validate the IP address
//
- while (( NULL != pPreviousPort )
- && ( pPreviousPort->pLinkSocket != pPort )) {
- pPreviousPort = pPreviousPort->pLinkSocket;
- }
- if ( NULL != pPreviousPort ) {
+ pConfig->StationPort = 0;
+ Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL )
+ : EFI_SUCCESS;
+ if ( !EFI_ERROR ( Status )) {
//
- // Remove the port from the middle of the socket list
+ // Set the port number
//
- pPreviousPort->pLinkSocket = pPort->pLinkSocket;
- }
- }
+ pConfig->StationPort = SwapBytes16 ( pIpAddress->sin_port );
- //
- // Locate the port in the service list
- //
- pService = pPort->pService;
- pPreviousPort = pService->pPortList;
- if ( pPreviousPort == pPort ) {
- //
- // Remove this port from the head of the service list
- //
- pService->pPortList = pPort->pLinkService;
- }
- else {
- //
- // Locate the port in the middle of the service list
- //
- while (( NULL != pPreviousPort )
- && ( pPreviousPort->pLinkService != pPort )) {
- pPreviousPort = pPreviousPort->pLinkService;
- }
- if ( NULL != pPreviousPort ) {
//
- // Remove the port from the middle of the service list
+ // Display the local address
//
- pPreviousPort->pLinkService = pPort->pLinkService;
- }
- }
-
- //
- // Empty the receive queue
- //
- ASSERT ( NULL == pSocket->pRxPacketListHead );
- ASSERT ( NULL == pSocket->pRxPacketListTail );
- ASSERT ( 0 == pSocket->RxBytes );
-
- //
- // Empty the receive free queue
- //
- while ( NULL != pSocket->pRxFree ) {
- pPacket = pSocket->pRxFree;
- pSocket->pRxFree = pPacket->pNext;
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- }
-
- //
- // Done with the receive event
- //
- pUdp4 = &pPort->Context.Udp4;
- if ( NULL != pUdp4->RxToken.Event ) {
- Status = gBS->CloseEvent ( pUdp4->RxToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed receive event\r\n",
- pUdp4->RxToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the receive event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the transmit event
- //
- if ( NULL != pUdp4->TxToken.Event ) {
- Status = gBS->CloseEvent ( pUdp4->TxToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed normal transmit event\r\n",
- pUdp4->TxToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the normal transmit event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the UDP protocol
- //
- pUdp4Service = pService->pInterface;
- if ( NULL != pUdp4->pProtocol ) {
- Status = gBS->CloseProtocol ( pUdp4->Handle,
- &gEfiUdp4ProtocolGuid,
- pLayer->ImageHandle,
- NULL );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags,
- "0x%08x: gEfiUdp4ProtocolGuid closed on controller 0x%08x\r\n",
- pUdp4->pProtocol,
- pUdp4->Handle ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close gEfiUdp4ProtocolGuid opened on controller 0x%08x, Status: %r\r\n",
- pUdp4->Handle,
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the UDP port
- //
- if ( NULL != pUdp4->Handle ) {
- Status = pUdp4Service->DestroyChild ( pUdp4Service,
- pUdp4->Handle );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Udp4 port handle destroyed\r\n",
- pUdp4->Handle ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
- "ERROR - Failed to destroy the Udp4 port handle, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
+ DEBUG (( DEBUG_BIND,
+ "0x%08x: Port, Local UDP4 Address: %d.%d.%d.%d:%d\r\n",
+ pPort,
+ pConfig->StationAddress.Addr[0],
+ pConfig->StationAddress.Addr[1],
+ pConfig->StationAddress.Addr[2],
+ pConfig->StationAddress.Addr[3],
+ pConfig->StationPort ));
}
}
//
- // Release the port structure
- //
- Status = gBS->FreePool ( pPort );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Free pPort, %d bytes\r\n",
- pPort,
- sizeof ( *pPort )));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
- "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
-
- //
- // Mark the socket as closed if necessary
- //
- if ( NULL == pSocket->pPortList ) {
- pSocket->State = SOCKET_STATE_CLOSED;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Socket State: SOCKET_STATE_CLOSED\r\n",
- pSocket ));
- }
-
- //
// Return the operation status
//
DBG_EXIT_STATUS ( Status );
@@ -651,288 +171,102 @@ EslUdpPortClose4 ( /**
- Start the close operation on a UDP4 port, state 1.
+ Free a receive packet
- Closing a port goes through the following states:
- 1. Port close starting - Mark the port as closing and wait for transmission to complete
- 2. Port TX close done - Transmissions complete, close the port and abort the receives
- 3. Port RX close done - Receive operations complete, close the port
- 4. Port closed - Release the port resources
-
- @param [in] pPort Address of the port structure.
- @param [in] bCloseNow Set TRUE to abort active transfers
- @param [in] DebugFlags Flags for debug messages
+ This routine performs the network specific operations necessary
+ to free a receive packet.
- @retval EFI_SUCCESS The port is closed, not normally returned
- @retval EFI_NOT_READY The port has started the closing process
- @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
- most likely the routine was called already.
+ This routine is called by ::EslSocketPortCloseTxDone to free a
+ receive packet.
+
+ @param [in] pPacket Address of an ::ESL_PACKET structure.
+ @param [in, out] pRxBytes Address of the count of RX bytes
**/
-EFI_STATUS
-EslUdpPortCloseStart4 (
- IN DT_PORT * pPort,
- IN BOOLEAN bCloseNow,
- IN UINTN DebugFlags
+VOID
+EslUdp4PacketFree (
+ IN ESL_PACKET * pPacket,
+ IN OUT size_t * pRxBytes
)
{
- DT_SOCKET * pSocket;
- EFI_STATUS Status;
+ EFI_UDP4_RECEIVE_DATA * pRxData;
DBG_ENTER ( );
//
- // Verify the socket layer synchronization
+ // Account for the receive bytes
//
- VERIFY_TPL ( TPL_SOCKETS );
+ pRxData = pPacket->Op.Udp4Rx.pRxData;
+ *pRxBytes -= pRxData->DataLength;
//
- // Mark the port as closing
+ // Disconnect the buffer from the packet
//
- Status = EFI_ALREADY_STARTED;
- pSocket = pPort->pSocket;
- pSocket->errno = EALREADY;
- if ( PORT_STATE_CLOSE_STARTED > pPort->State ) {
-
- //
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_STARTED;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n",
- pPort ));
- pPort->bCloseNow = bCloseNow;
- pPort->DebugFlags = DebugFlags;
-
- //
- // Determine if transmits are complete
- //
- Status = EslUdpPortCloseTxDone4 ( pPort );
- }
+ pPacket->Op.Udp4Rx.pRxData = NULL;
//
- // Return the operation status
+ // Return the buffer to the UDP4 driver
//
- DBG_EXIT_STATUS ( Status );
- return Status;
+ gBS->SignalEvent ( pRxData->RecycleSignal );
+ DBG_EXIT ( );
}
/**
- Port close state 3
+ Initialize the network specific portions of an ::ESL_PORT structure.
- Continue the close operation after the receive is complete.
+ This routine initializes the network specific portions of an
+ ::ESL_PORT structure for use by the socket.
- @param [in] pPort Address of the port structure.
+ This support routine is called by ::EslSocketPortAllocate
+ to connect the socket with the underlying network adapter
+ running the UDPv4 protocol.
- @retval EFI_SUCCESS The port is closed
- @retval EFI_NOT_READY The port is still closing
- @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
- most likely the routine was called already.
+ @param [in] pPort Address of an ESL_PORT structure
+ @param [in] DebugFlags Flags for debug messages
-**/
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
EFI_STATUS
-EslUdpPortCloseRxDone4 (
- IN DT_PORT * pPort
+EslUdp4PortAllocate (
+ IN ESL_PORT * pPort,
+ IN UINTN DebugFlags
)
{
- PORT_STATE PortState;
- DT_SOCKET * pSocket;
- DT_UDP4_CONTEXT * pUdp4;
+ EFI_UDP4_CONFIG_DATA * pConfig;
+ ESL_SOCKET * pSocket;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Verify that the port is closing
+ // Initialize the port
//
- Status = EFI_ALREADY_STARTED;
pSocket = pPort->pSocket;
- pSocket->errno = EALREADY;
- PortState = pPort->State;
- if (( PORT_STATE_CLOSE_TX_DONE == PortState )
- || ( PORT_STATE_CLOSE_DONE == PortState )) {
- //
- // Determine if the receive operation is pending
- //
- Status = EFI_NOT_READY;
- pSocket->errno = EAGAIN;
- pUdp4 = &pPort->Context.Udp4;
- if ( NULL == pUdp4->pReceivePending ) {
- //
- // The receive operation is complete
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_RX_DONE;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n",
- pPort ));
-
- //
- // The close operation has completed
- // Release the port resources
- //
- Status = EslUdpPortClose4 ( pPort );
- }
- else {
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close: Receive still pending!\r\n",
- pPort ));
- }
- }
+ pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Udp4Tx.TxData );
+ pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Tx.Event );
+ pSocket->TxTokenOffset = OFFSET_OF ( EFI_UDP4_COMPLETION_TOKEN, Packet.TxData );
//
- // Return the operation status
+ // Save the cancel, receive and transmit addresses
//
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Port close state 2
-
- Continue the close operation after the transmission is complete.
-
- @param [in] pPort Address of the port structure.
-
- @retval EFI_SUCCESS The port is closed, not normally returned
- @retval EFI_NOT_READY The port is still closing
- @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
- most likely the routine was called already.
-
-**/
-EFI_STATUS
-EslUdpPortCloseTxDone4 (
- IN DT_PORT * pPort
- )
-{
- DT_PACKET * pPacket;
- DT_SOCKET * pSocket;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_UDP4_PROTOCOL * pUdp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
+ pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.UDPv4->Configure;
+ pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Cancel;
+ pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Receive;
+ pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Transmit;
//
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
+ // Set the configuration flags
//
- // All transmissions are complete or must be stopped
- // Mark the port as TX complete
- //
- Status = EFI_ALREADY_STARTED;
- if ( PORT_STATE_CLOSE_STARTED == pPort->State ) {
- //
- // Verify that the transmissions are complete
- //
- pSocket = pPort->pSocket;
- if ( pPort->bCloseNow
- || ( EFI_SUCCESS != pSocket->TxError )
- || ( 0 == pSocket->TxBytes )) {
- //
- // Start the close operation on the port
- //
- pUdp4 = &pPort->Context.Udp4;
- pUdp4Protocol = pUdp4->pProtocol;
- if ( !pUdp4->bConfigured ) {
- //
- // Skip the close operation since the port is not
- // configured
- //
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_DONE;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n",
- pPort ));
- Status = EFI_SUCCESS;
- }
- else {
- //
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_TX_DONE;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n",
- pPort ));
-
- //
- // Empty the receive queue
- //
- while ( NULL != pSocket->pRxPacketListHead ) {
- pPacket = pSocket->pRxPacketListHead;
- pSocket->pRxPacketListHead = pPacket->pNext;
- pSocket->RxBytes -= pPacket->Op.Udp4Rx.pRxData->DataLength;
-
- //
- // Return the buffer to the UDP4 driver
- //
- gBS->SignalEvent ( pPacket->Op.Udp4Rx.pRxData->RecycleSignal );
-
- //
- // Done with this packet
- //
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- }
- pSocket->pRxPacketListTail = NULL;
- ASSERT ( 0 == pSocket->RxBytes );
-
- //
- // Reset the port, cancel the outstanding receive
- //
- Status = pUdp4Protocol->Configure ( pUdp4Protocol,
- NULL );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port reset\r\n",
- pPort ));
-
- //
- // Free the receive packet
- //
- Status = gBS->CheckEvent ( pUdp4->RxToken.Event );
- if ( EFI_SUCCESS != Status ) {
- EslSocketPacketFree ( pUdp4->pReceivePending, DEBUG_CLOSE );
- pUdp4->pReceivePending = NULL;
- Status = EFI_SUCCESS;
- }
- }
- else {
- DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "ERROR - Port 0x%08x reset failed, Status: %r\r\n",
- pPort,
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Determine if the receive operation is pending
- //
- if ( !EFI_ERROR ( Status )) {
- Status = EslUdpPortCloseRxDone4 ( pPort );
- }
- }
- else {
- //
- // Transmissions are still active, exit
- //
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close: Transmits are still pending!\r\n",
- pPort ));
- Status = EFI_NOT_READY;
- pSocket->errno = EAGAIN;
- }
- }
+ pConfig = &pPort->Context.Udp4.ConfigData;
+ pConfig->TimeToLive = 255;
+ pConfig->AcceptAnyPort = FALSE;
+ pConfig->AcceptBroadcast = FALSE;
+ pConfig->AcceptPromiscuous = FALSE;
+ pConfig->AllowDuplicatePort = TRUE;
+ pConfig->DoNotFragment = TRUE;
+ Status = EFI_SUCCESS;
//
// Return the operation status
@@ -943,603 +277,192 @@ EslUdpPortCloseTxDone4 ( /**
- Connect to a remote system via the network.
+ Receive data from a network connection.
- The ::UdpConnectStart4= routine sets the remote address for the connection.
+ 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.
- @param [in] pSocket Address of the socket structure.
+ This routine is called by ::EslSocketReceive to handle the network
+ specific receive operation to support SOCK_DGRAM sockets.
- @param [in] pSockAddr Network address of the remote system.
-
- @param [in] SockAddrLength Length in bytes of the network address.
+ @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
- @retval EFI_SUCCESS The connection was successfully established.
- @retval EFI_NOT_READY The connection is in progress, call this routine again.
- @retval Others The connection attempt failed.
+ @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 [out] pSkipBytes Address to receive the number of bytes skipped
+
+ @return Returns the address of the next free byte in the buffer.
**/
-EFI_STATUS
-EslUdpConnect4 (
- IN DT_SOCKET * pSocket,
- IN const struct sockaddr * pSockAddr,
- IN socklen_t SockAddrLength
+UINT8 *
+EslUdp4Receive (
+ 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,
+ OUT size_t * pSkipBytes
)
{
- struct sockaddr_in LocalAddress;
- DT_PORT * pPort;
+ size_t DataBytes;
struct sockaddr_in * pRemoteAddress;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_STATUS Status;
+ EFI_UDP4_RECEIVE_DATA * pRxData;
DBG_ENTER ( );
+ pRxData = pPacket->Op.Udp4Rx.pRxData;
//
- // Assume failure
- //
- Status = EFI_NETWORK_UNREACHABLE;
- pSocket->errno = ENETUNREACH;
-
+ // Return the remote system address if requested
//
- // Get the address
- //
- pRemoteAddress = (struct sockaddr_in *)pSockAddr;
-
- //
- // Validate the address length
- //
- if ( SockAddrLength >= ( sizeof ( *pRemoteAddress )
- - sizeof ( pRemoteAddress->sin_zero ))) {
- //
- // Determine if BIND was already called
- //
- if ( NULL == pSocket->pPortList ) {
- //
- // Allow any local port
- //
- ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));
- LocalAddress.sin_len = sizeof ( LocalAddress );
- LocalAddress.sin_family = AF_INET;
- Status = EslSocketBind ( &pSocket->SocketProtocol,
- (struct sockaddr *)&LocalAddress,
- LocalAddress.sin_len,
- &pSocket->errno );
- }
-
+ if ( NULL != pAddress ) {
//
- // Walk the list of ports
+ // Build the remote address
//
- pPort = pSocket->pPortList;
- while ( NULL != pPort ) {
- //
- // Set the remote address
- //
- pUdp4 = &pPort->Context.Udp4;
- pUdp4->ConfigData.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );
- pUdp4->ConfigData.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
- pUdp4->ConfigData.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
- pUdp4->ConfigData.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
- pUdp4->ConfigData.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port );
-
- //
- // At least one path exists
- //
- Status = EFI_SUCCESS;
- pSocket->errno = 0;
-
- //
- // Set the next port
- //
- pPort = pPort->pLinkSocket;
- }
- }
- else {
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Invalid UDP4 address length: %d\r\n",
- SockAddrLength ));
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
+ 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 );
}
//
- // Return the connect status
+ // Copy the received data
//
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Get the local socket address
-
- @param [in] pSocket Address of the socket structure.
-
- @param [out] pAddress Network address to receive the local system address
-
- @param [in,out] pAddressLength Length of the local network address structure
-
- @retval EFI_SUCCESS - Address available
- @retval Other - Failed to get the address
-
-**/
-EFI_STATUS
-EslUdpGetLocalAddress4 (
- IN DT_SOCKET * pSocket,
- OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
- )
-{
- socklen_t LengthInBytes;
- DT_PORT * pPort;
- struct sockaddr_in * pLocalAddress;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
+ pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,
+ (EFI_IP4_FRAGMENT_DATA *)&pRxData->FragmentTable[0],
+ BufferLength,
+ pBuffer,
+ &DataBytes );
//
- // Verify the socket layer synchronization
+ // Determine if the data is being read
//
- VERIFY_TPL ( TPL_SOCKETS );
+ if ( *pbConsumePacket ) {
+ //
+ // Display for the bytes consumed
+ //
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port account for 0x%08x bytes\r\n",
+ pPort,
+ DataBytes ));
- //
- // Verify that there is just a single connection
- //
- pPort = pSocket->pPortList;
- if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
//
- // Verify the address length
+ // Account for any discarded data
//
- LengthInBytes = sizeof ( struct sockaddr_in );
- if ( LengthInBytes <= * pAddressLength ) {
- //
- // Return the local address
- //
- pUdp4 = &pPort->Context.Udp4;
- pLocalAddress = (struct sockaddr_in *)pAddress;
- ZeroMem ( pLocalAddress, LengthInBytes );
- pLocalAddress->sin_family = AF_INET;
- pLocalAddress->sin_len = (uint8_t)LengthInBytes;
- pLocalAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.StationPort );
- CopyMem ( &pLocalAddress->sin_addr,
- &pUdp4->ConfigData.StationAddress.Addr[0],
- sizeof ( pLocalAddress->sin_addr ));
- pSocket->errno = 0;
- Status = EFI_SUCCESS;
- }
- else {
- pSocket->errno = EINVAL;
- Status = EFI_INVALID_PARAMETER;
- }
+ *pSkipBytes = pRxData->DataLength - DataBytes;
}
- else {
- pSocket->errno = ENOTCONN;
- Status = EFI_NOT_STARTED;
- }
-
+
//
- // 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;
}
/**
Get the remote socket address
- @param [in] pSocket Address of the socket structure.
+ This routine returns the address of the remote connection point
+ associated with the SOCK_DGRAM socket.
- @param [out] pAddress Network address to receive the remote system address
+ This routine is called by ::EslSocketGetPeerAddress to detemine
+ the UDPv4 address and port number associated with the network adapter.
- @param [in,out] pAddressLength Length of the remote network address structure
+ @param [in] pPort Address of an ::ESL_PORT structure.
- @retval EFI_SUCCESS - Address available
- @retval Other - Failed to get the address
+ @param [out] pAddress Network address to receive the remote system address
**/
-EFI_STATUS
-EslUdpGetRemoteAddress4 (
- IN DT_SOCKET * pSocket,
- OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
+VOID
+EslUdp4RemoteAddressGet (
+ IN ESL_PORT * pPort,
+ OUT struct sockaddr * pAddress
)
{
- socklen_t LengthInBytes;
- DT_PORT * pPort;
struct sockaddr_in * pRemoteAddress;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_STATUS Status;
+ ESL_UDP4_CONTEXT * pUdp4;
DBG_ENTER ( );
//
- // Verify the socket layer synchronization
+ // Return the remote address
//
- VERIFY_TPL ( TPL_SOCKETS );
+ pUdp4 = &pPort->Context.Udp4;
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ pRemoteAddress->sin_family = AF_INET;
+ pRemoteAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.RemotePort );
+ CopyMem ( &pRemoteAddress->sin_addr,
+ &pUdp4->ConfigData.RemoteAddress.Addr[0],
+ sizeof ( pRemoteAddress->sin_addr ));
- //
- // Verify that there is just a single connection
- //
- pPort = pSocket->pPortList;
- if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
- //
- // Verify the address length
- //
- LengthInBytes = sizeof ( struct sockaddr_in );
- if ( LengthInBytes <= * pAddressLength ) {
- //
- // Return the local address
- //
- pUdp4 = &pPort->Context.Udp4;
- pRemoteAddress = (struct sockaddr_in *)pAddress;
- ZeroMem ( pRemoteAddress, LengthInBytes );
- pRemoteAddress->sin_family = AF_INET;
- pRemoteAddress->sin_len = (uint8_t)LengthInBytes;
- pRemoteAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.RemotePort );
- CopyMem ( &pRemoteAddress->sin_addr,
- &pUdp4->ConfigData.RemoteAddress.Addr[0],
- sizeof ( pRemoteAddress->sin_addr ));
- pSocket->errno = 0;
- Status = EFI_SUCCESS;
- }
- else {
- pSocket->errno = EINVAL;
- Status = EFI_INVALID_PARAMETER;
- }
- }
- else {
- pSocket->errno = ENOTCONN;
- Status = EFI_NOT_STARTED;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
+ DBG_EXIT ( );
}
/**
- Receive data from a network connection.
-
- To minimize the number of buffer copies, the ::UdpRxComplete4
- routine queues the UDP4 driver's buffer to a list of datagrams
- waiting to be received. The socket driver holds on to the
- buffers from the UDP4 driver until the application layer requests
- the data or the socket is closed.
-
- The application calls this routine in the socket layer to
- receive datagrams from one or more remote systems. This routine
- removes the next available datagram from the list of datagrams
- and copies the data from the UDP4 driver's buffer into the
- application's buffer. The UDP4 driver's buffer is then returned.
-
- @param [in] pSocket Address of a DT_SOCKET structure
-
- @param [in] Flags Message control flags
-
- @param [in] BufferLength Length of the the buffer
+ Set the remote address
- @param [in] pBuffer Address of a buffer to receive the data.
+ This routine sets the remote address in the port.
- @param [in] pDataLength Number of received data bytes in the buffer.
+ This routine is called by ::EslSocketConnect to specify the
+ remote network address.
- @param [out] pAddress Network address to receive the remote system address
-
- @param [in,out] pAddressLength Length of the remote network address structure
-
- @retval EFI_SUCCESS - Socket data successfully received
-
-**/
-EFI_STATUS
-EslUdpReceive4 (
- IN DT_SOCKET * pSocket,
- IN INT32 Flags,
- IN size_t BufferLength,
- IN UINT8 * pBuffer,
- OUT size_t * pDataLength,
- OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
- )
-{
- socklen_t AddressLength;
- size_t BytesToCopy;
- size_t DataBytes;
- UINT32 Fragment;
- in_addr_t IpAddress;
- size_t LengthInBytes;
- UINT8 * pData;
- DT_PACKET * pPacket;
- DT_PORT * pPort;
- struct sockaddr_in * pRemoteAddress;
- EFI_UDP4_RECEIVE_DATA * pRxData;
- DT_UDP4_CONTEXT * pUdp4;
- struct sockaddr_in RemoteAddress;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume failure
- //
- Status = EFI_UNSUPPORTED;
- pSocket->errno = ENOTCONN;
-
- //
- // Verify that the socket is connected
- //
- if (( SOCKET_STATE_CONNECTED == pSocket->State )
- || ( PORT_STATE_RX_ERROR == pSocket->State )) {
- //
- // Locate the port
- //
- 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;
- do {
- //
- // 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 );
- } while ( BufferLength > LengthInBytes );
-
- //
- // 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 == pUdp4->pReceivePending )
- && ( MAX_RX_DATA > pSocket->RxBytes )) {
- EslUdpRxStart4 ( 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;
- }
- }
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
+ @param [in] pPort Address of an ::ESL_PORT structure.
+ @param [in] pSockAddr Network address of the remote system.
-/**
- Cancel the receive operations
+ @param [in] SockAddrLength Length in bytes of the network address.
- @param [in] pSocket Address of a DT_SOCKET structure
-
- @retval EFI_SUCCESS - The cancel was successful
+ @retval EFI_SUCCESS The operation was successful
**/
EFI_STATUS
-EslUdpRxCancel4 (
- IN DT_SOCKET * pSocket
+EslUdp4RemoteAddressSet (
+ IN ESL_PORT * pPort,
+ IN CONST struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
)
{
- DT_PACKET * pPacket;
- DT_PORT * pPort;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_UDP4_PROTOCOL * pUdp4Protocol;
+ CONST struct sockaddr_in * pRemoteAddress;
+ ESL_UDP4_CONTEXT * pUdp4;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Assume failure
- //
- Status = EFI_NOT_FOUND;
-
+ // Set the remote address
//
- // Locate the port
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine if a receive is pending
- //
- pUdp4 = &pPort->Context.Udp4;
- pPacket = pUdp4->pReceivePending;
- if ( NULL != pPacket ) {
- //
- // Attempt to cancel the receive operation
- //
- pUdp4Protocol = pUdp4->pProtocol;
- Status = pUdp4Protocol->Cancel ( pUdp4Protocol,
- &pUdp4->RxToken );
- if ( EFI_NOT_FOUND == Status ) {
- //
- // The receive is complete
- //
- Status = EFI_SUCCESS;
- }
- }
- }
+ pUdp4 = &pPort->Context.Udp4;
+ pRemoteAddress = (struct sockaddr_in *)pSockAddr;
+ pUdp4->ConfigData.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );
+ pUdp4->ConfigData.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
+ pUdp4->ConfigData.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
+ pUdp4->ConfigData.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
+ pUdp4->ConfigData.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port );
+ Status = EFI_SUCCESS;
//
// Return the operation status
@@ -1552,351 +475,102 @@ EslUdpRxCancel4 ( /**
Process the receive completion
- Keep the UDP4 driver's buffer and append it to the list of
- datagrams for the application to receive. The UDP4 driver's
- buffer will be returned by either ::UdpReceive4 or
- ::UdpPortCloseTxDone4.
+ This routine keeps the UDPv4 driver's buffer and queues it in
+ in FIFO order to the data queue. The UDP4 driver's buffer will
+ be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone.
+ See the \ref ReceiveEngine section.
- @param Event The receive completion event
+ This routine is called by the UDPv4 driver when data is
+ received.
- @param pPort The DT_PORT structure address
+ @param [in] Event The receive completion event
+
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
**/
VOID
-EslUdpRxComplete4 (
+EslUdp4RxComplete (
IN EFI_EVENT Event,
- IN DT_PORT * pPort
+ IN ESL_IO_MGMT * pIo
)
{
size_t LengthInBytes;
- DT_PACKET * pPacket;
- DT_PACKET * pPrevious;
+ ESL_PACKET * pPacket;
EFI_UDP4_RECEIVE_DATA * pRxData;
- DT_SOCKET * pSocket;
- DT_UDP4_CONTEXT * pUdp4;
EFI_STATUS Status;
DBG_ENTER ( );
-
- //
- // Mark this receive complete
- //
- pUdp4 = &pPort->Context.Udp4;
- pPacket = pUdp4->pReceivePending;
- pUdp4->pReceivePending = NULL;
-
+
//
- // Determine if this receive was successful
+ // Get the operation status.
//
- pSocket = pPort->pSocket;
- Status = pUdp4->RxToken.Status;
- if (( !EFI_ERROR ( Status )) && ( !pSocket->bRxDisable )) {
- pRxData = pUdp4->RxToken.Packet.RxData;
- if ( PORT_STATE_CLOSE_STARTED >= pPort->State ) {
- //
- // Save the data in the packet
- //
- pPacket->Op.Udp4Rx.pRxData = pRxData;
-
- //
- // Queue this packet
- //
- pPrevious = pSocket->pRxPacketListTail;
- if ( NULL == pPrevious ) {
- pSocket->pRxPacketListHead = pPacket;
- }
- else {
- pPrevious->pNext = pPacket;
- }
- pSocket->pRxPacketListTail = pPacket;
-
- //
- // Account for the normal data
- //
- LengthInBytes = pRxData->DataLength;
- pSocket->RxBytes += LengthInBytes;
-
- //
- // Log the received data
- //
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "Received packet from: %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 ));
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "Received packet sent to: %d.%d.%d.%d:%d\r\n",
- pRxData->UdpSession.DestinationAddress.Addr[0],
- pRxData->UdpSession.DestinationAddress.Addr[1],
- pRxData->UdpSession.DestinationAddress.Addr[2],
- pRxData->UdpSession.DestinationAddress.Addr[3],
- pRxData->UdpSession.DestinationPort ));
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "0x%08x: Packet queued on port 0x%08x with 0x%08x bytes of data\r\n",
- pPacket,
- pPort,
- LengthInBytes ));
-
- //
- // Attempt to restart this receive operation
- //
- if ( pSocket->MaxRxBuf > pSocket->RxBytes ) {
- EslUdpRxStart4 ( pPort );
- }
- else {
- DEBUG (( DEBUG_RX,
- "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n",
- pPort,
- pSocket->RxBytes ));
- }
- }
- else {
- //
- // The port is being closed
- // Return the buffer to the UDP4 driver
- //
- gBS->SignalEvent ( pRxData->RecycleSignal );
-
- //
- // Free the packet
- //
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- }
- }
- else
- {
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "ERROR - Receiving packet 0x%08x, on port 0x%08x, Status:%r\r\n",
- pPacket,
- pPort,
- Status ));
-
- //
- // Receive error, free the packet save the error
- //
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- if ( !EFI_ERROR ( pSocket->RxError )) {
- pSocket->RxError = Status;
- }
-
- //
- // Update the port state
- //
- if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
- EslUdpPortCloseRxDone4 ( pPort );
- }
- else {
- if ( EFI_ERROR ( Status )) {
- pPort->State = PORT_STATE_RX_ERROR;
- }
- }
- }
+ Status = pIo->Token.Udp4Rx.Status;
- DBG_EXIT ( );
-}
-
-
-/**
- Start a receive operation
-
- @param [in] pPort Address of the DT_PORT structure.
-
- **/
-VOID
-EslUdpRxStart4 (
- IN DT_PORT * pPort
- )
-{
- DT_PACKET * pPacket;
- DT_SOCKET * pSocket;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_UDP4_PROTOCOL * pUdp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
//
- // Determine if a receive is already pending
+ // Get the packet length
//
- Status = EFI_SUCCESS;
- pPacket = NULL;
- pSocket = pPort->pSocket;
- pUdp4 = &pPort->Context.Udp4;
- if ( !EFI_ERROR ( pPort->pSocket->RxError )) {
- if (( NULL == pUdp4->pReceivePending )
- && ( PORT_STATE_CLOSE_STARTED > pPort->State )) {
- //
- // Determine if there are any free packets
- //
- pPacket = pSocket->pRxFree;
- if ( NULL != pPacket ) {
- //
- // Remove this packet from the free list
- //
- pSocket->pRxFree = pPacket->pNext;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port removed packet 0x%08x from free list\r\n",
- pPort,
- pPacket ));
- }
- else {
- //
- // Allocate a packet structure
- //
- Status = EslSocketPacketAllocate ( &pPacket,
- sizeof ( pPacket->Op.Udp4Rx ),
- DEBUG_RX );
- if ( EFI_ERROR ( Status )) {
- pPacket = NULL;
- DEBUG (( DEBUG_ERROR | DEBUG_RX,
- "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",
- pPort,
- Status ));
- }
- }
-
- //
- // Determine if a packet is available
- //
- if ( NULL != pPacket ) {
- //
- // Initialize the buffer for receive
- //
- pPacket->pNext = NULL;
- pPacket->Op.Udp4Rx.pRxData = NULL;
- pUdp4->RxToken.Packet.RxData = NULL;
- pUdp4->pReceivePending = pPacket;
-
- //
- // Start the receive on the packet
- //
- pUdp4Protocol = pUdp4->pProtocol;
- Status = pUdp4Protocol->Receive ( pUdp4Protocol,
- &pUdp4->RxToken );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "0x%08x: Packet receive pending on port 0x%08x\r\n",
- pPacket,
- pPort ));
- }
- else {
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
- if ( !EFI_ERROR ( pSocket->RxError )) {
- //
- // Save the error status
- //
- pSocket->RxError = Status;
- }
-
- //
- // Free the packet
- //
- pUdp4->pReceivePending = NULL;
- pPacket->pNext = pSocket->pRxFree;
- pSocket->pRxFree = pPacket;
- }
- }
- }
- }
-
- DBG_EXIT ( );
-}
-
-
-/**
- Shutdown the UDP4 service.
-
- This routine undoes the work performed by ::UdpInitialize4.
-
- @param [in] pService DT_SERVICE structure address
-
-**/
-VOID
-EFIAPI
-EslUdpShutdown4 (
- IN DT_SERVICE * pService
- )
-{
- DT_LAYER * pLayer;
- DT_PORT * pPort;
- DT_SERVICE * pPreviousService;
-
- DBG_ENTER ( );
+ pRxData = pIo->Token.Udp4Rx.Packet.RxData;
+ LengthInBytes = pRxData->DataLength;
//
- // Verify the socket layer synchronization
+ // +--------------------+ +-----------------------+
+ // | ESL_IO_MGMT | | Data Buffer |
+ // | | | (Driver owned) |
+ // | +---------------+ +-----------------------+
+ // | | Token | ^
+ // | | Rx Event | |
+ // | | | +-----------------------+
+ // | | RxData --> | EFI_UDP4_RECEIVE_DATA |
+ // +----+---------------+ | (Driver owned) |
+ // +-----------------------+
+ // +--------------------+ ^
+ // | ESL_PACKET | .
+ // | | .
+ // | +---------------+ .
+ // | | pRxData --> NULL .......
+ // +----+---------------+
//
- VERIFY_TPL ( TPL_SOCKETS );
-
//
- // Walk the list of ports
+ // Save the data in the packet
//
- do {
- pPort = pService->pPortList;
- if ( NULL != pPort ) {
- //
- // Remove the port from the port list
- //
- pService->pPortList = pPort->pLinkService;
-
- //
- // Close the port
- // TODO: Fix this
- //
-// pPort->pfnClosePort ( pPort, 0 );
- }
- } while ( NULL != pPort );
+ pPacket = pIo->pPacket;
+ pPacket->Op.Udp4Rx.pRxData = pRxData;
//
- // Remove the service from the service list
+ // Complete this request
//
- pLayer = &mEslLayer;
- pPreviousService = pLayer->pUdp4List;
- if ( pService == pPreviousService ) {
- //
- // Remove the service from the beginning of the list
- //
- pLayer->pUdp4List = pService->pNext;
- }
- else {
- //
- // Remove the service from the middle of the list
- //
- while ( NULL != pPreviousService ) {
- if ( pService == pPreviousService->pNext ) {
- pPreviousService->pNext = pService->pNext;
- break;
- }
- }
- }
-
+ EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );
DBG_EXIT ( );
}
/**
- Determine if the sockedt is configured.
+ Determine if the socket is configured.
+ This routine uses the flag ESL_SOCKET::bConfigured to determine
+ if the network layer's configuration routine has been called.
+ This routine calls the bind and configuration routines if they
+ were not already called. After the port is configured, the
+ \ref ReceiveEngine is started.
+
+ This routine is called by EslSocketIsConfigured to verify
+ that the socket is configured.
+
+ @param [in] pSocket Address of an ::ESL_SOCKET structure
- @param [in] pSocket Address of a DT_SOCKET structure
-
@retval EFI_SUCCESS - The port is connected
@retval EFI_NOT_STARTED - The port is not connected
**/
EFI_STATUS
- EslUdpSocketIsConfigured4 (
- IN DT_SOCKET * pSocket
+ EslUdp4SocketIsConfigured (
+ IN ESL_SOCKET * pSocket
)
{
- DT_PORT * pPort;
- DT_PORT * pNextPort;
- DT_UDP4_CONTEXT * pUdp4;
+ EFI_UDP4_CONFIG_DATA * pConfigData;
+ ESL_PORT * pPort;
+ ESL_PORT * pNextPort;
+ ESL_UDP4_CONTEXT * pUdp4;
EFI_UDP4_PROTOCOL * pUdp4Protocol;
EFI_STATUS Status;
struct sockaddr_in LocalAddress;
@@ -1920,9 +594,10 @@ EslUdpShutdown4 ( LocalAddress.sin_family = AF_INET;
LocalAddress.sin_addr.s_addr = 0;
LocalAddress.sin_port = 0;
- Status = EslUdpBind4 ( pSocket,
- (struct sockaddr *)&LocalAddress,
- LocalAddress.sin_len );
+ Status = EslSocketBind ( &pSocket->SocketProtocol,
+ (struct sockaddr *)&LocalAddress,
+ LocalAddress.sin_len,
+ &pSocket->errno );
}
//
@@ -1935,9 +610,33 @@ EslUdpShutdown4 ( //
pNextPort = pPort->pLinkSocket;
pUdp4 = &pPort->Context.Udp4;
- pUdp4Protocol = pUdp4->pProtocol;
+ pUdp4Protocol = pPort->pProtocol.UDPv4;
+ pConfigData = &pUdp4->ConfigData;
+ DEBUG (( DEBUG_TX,
+ "0x%08x: pPort Configuring for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
+ pPort,
+ pConfigData->StationAddress.Addr[0],
+ pConfigData->StationAddress.Addr[1],
+ pConfigData->StationAddress.Addr[2],
+ pConfigData->StationAddress.Addr[3],
+ pConfigData->StationPort,
+ pConfigData->RemoteAddress.Addr[0],
+ pConfigData->RemoteAddress.Addr[1],
+ pConfigData->RemoteAddress.Addr[2],
+ pConfigData->RemoteAddress.Addr[3],
+ pConfigData->RemotePort ));
Status = pUdp4Protocol->Configure ( pUdp4Protocol,
- &pUdp4->ConfigData );
+ pConfigData );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Update the configuration data
+ //
+ Status = pUdp4Protocol->GetModeData ( pUdp4Protocol,
+ pConfigData,
+ NULL,
+ NULL,
+ NULL );
+ }
if ( EFI_ERROR ( Status )) {
DEBUG (( DEBUG_LISTEN,
"ERROR - Failed to configure the Udp4 port, Status: %r\r\n",
@@ -1970,15 +669,25 @@ EslUdpShutdown4 ( }
}
else {
- DEBUG (( DEBUG_LISTEN,
- "0x%08x: Port configured\r\n",
- pPort ));
- pUdp4->bConfigured = TRUE;
+ DEBUG (( DEBUG_TX,
+ "0x%08x: pPort Configured for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
+ pPort,
+ pConfigData->StationAddress.Addr[0],
+ pConfigData->StationAddress.Addr[1],
+ pConfigData->StationAddress.Addr[2],
+ pConfigData->StationAddress.Addr[3],
+ pConfigData->StationPort,
+ pConfigData->RemoteAddress.Addr[0],
+ pConfigData->RemoteAddress.Addr[1],
+ pConfigData->RemoteAddress.Addr[2],
+ pConfigData->RemoteAddress.Addr[3],
+ pConfigData->RemotePort ));
+ pPort->bConfigured = TRUE;
//
// Start the first read on the port
//
- EslUdpRxStart4 ( pPort );
+ EslSocketRxStart ( pPort );
//
// The socket is connected
@@ -2018,10 +727,15 @@ EslUdpShutdown4 ( /**
Buffer data for transmission over a network connection.
- This routine is called by the socket layer API to buffer
+ This routine buffers data for the transmit engine in the normal
+ data queue. When the \ref TransmitEngine has resources, this
+ routine will start the transmission of the next buffer on the
+ network connection.
+
+ This routine is called by ::EslSocketTransmit to buffer
data for transmission. The data is copied into a local buffer
freeing the application buffer for reuse upon return. When
- necessary, this routine will start the transmit engine that
+ necessary, this routine starts the transmit engine that
performs the data transmission on the network connection. The
transmit engine transmits the data a packet at a time over the
network connection.
@@ -2030,7 +744,7 @@ EslUdpShutdown4 ( during the close operation. Only buffering errors are returned
during the current transmission attempt.
- @param [in] pSocket Address of a DT_SOCKET structure
+ @param [in] pSocket Address of an ::ESL_SOCKET structure
@param [in] Flags Message control flags
@@ -2048,8 +762,8 @@ EslUdpShutdown4 ( **/
EFI_STATUS
-EslUdpTxBuffer4 (
- IN DT_SOCKET * pSocket,
+EslUdp4TxBuffer (
+ IN ESL_SOCKET * pSocket,
IN int Flags,
IN size_t BufferLength,
IN CONST UINT8 * pBuffer,
@@ -2058,15 +772,13 @@ EslUdpTxBuffer4 ( IN socklen_t AddressLength
)
{
- DT_PACKET * pPacket;
- DT_PACKET * pPreviousPacket;
- DT_PACKET ** ppPacket;
- DT_PORT * pPort;
+ ESL_PACKET * pPacket;
+ ESL_PACKET * pPreviousPacket;
+ ESL_PORT * pPort;
const struct sockaddr_in * pRemoteAddress;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_UDP4_COMPLETION_TOKEN * pToken;
+ ESL_UDP4_CONTEXT * pUdp4;
size_t * pTxBytes;
- DT_UDP4_TX_DATA * pTxData;
+ ESL_UDP4_TX_DATA * pTxData;
EFI_STATUS Status;
EFI_TPL TplPrevious;
@@ -2077,7 +789,7 @@ EslUdpTxBuffer4 ( //
Status = EFI_UNSUPPORTED;
pSocket->errno = ENOTCONN;
- * pDataLength = 0;
+ *pDataLength = 0;
//
// Verify that the socket is connected
@@ -2092,8 +804,6 @@ EslUdpTxBuffer4 ( // Determine the queue head
//
pUdp4 = &pPort->Context.Udp4;
- ppPacket = &pUdp4->pTxPacket;
- pToken = &pUdp4->TxToken;
pTxBytes = &pSocket->TxBytes;
//
@@ -2108,6 +818,7 @@ EslUdpTxBuffer4 ( sizeof ( pPacket->Op.Udp4Tx )
- sizeof ( pPacket->Op.Udp4Tx.Buffer )
+ BufferLength,
+ 0,
DEBUG_TX );
if ( !EFI_ERROR ( Status )) {
//
@@ -2120,16 +831,18 @@ EslUdpTxBuffer4 ( pTxData->TxData.FragmentCount = 1;
pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength;
pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Udp4Tx.Buffer[0];
+ pTxData->RetransmitCount = 0;
//
// Set the remote system address if necessary
//
+ pTxData->TxData.UdpSessionData = NULL;
if ( NULL != pAddress ) {
pRemoteAddress = (const struct sockaddr_in *)pAddress;
- pTxData->Session.SourceAddress.Addr[0] = 0;
- pTxData->Session.SourceAddress.Addr[1] = 0;
- pTxData->Session.SourceAddress.Addr[2] = 0;
- pTxData->Session.SourceAddress.Addr[3] = 0;
+ pTxData->Session.SourceAddress.Addr[0] = pUdp4->ConfigData.StationAddress.Addr[0];
+ pTxData->Session.SourceAddress.Addr[1] = pUdp4->ConfigData.StationAddress.Addr[1];
+ pTxData->Session.SourceAddress.Addr[2] = pUdp4->ConfigData.StationAddress.Addr[2];
+ pTxData->Session.SourceAddress.Addr[3] = pUdp4->ConfigData.StationAddress.Addr[3];
pTxData->Session.SourcePort = 0;
pTxData->Session.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr;
pTxData->Session.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
@@ -2192,8 +905,12 @@ EslUdpTxBuffer4 ( //
// Start the transmit engine if it is idle
//
- if ( NULL == pUdp4->pTxPacket ) {
- EslUdpTxStart4 ( pSocket->pPortList );
+ if ( NULL != pPort->pTxFree ) {
+ EslSocketTxStart ( pPort,
+ &pSocket->pTxPacketListHead,
+ &pSocket->pTxPacketListTail,
+ &pPort->pTxActive,
+ &pPort->pTxFree );
}
}
else {
@@ -2243,23 +960,27 @@ EslUdpTxBuffer4 ( /**
Process the transmit completion
- @param Event The normal transmit completion event
+ This routine use ::EslSocketTxComplete to perform the transmit
+ completion processing for data packets.
- @param pPort The DT_PORT structure address
+ This routine is called by the UDPv4 network layer when a data
+ transmit request completes.
+
+ @param [in] Event The normal transmit completion event
+
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
**/
VOID
-EslUdpTxComplete4 (
+EslUdp4TxComplete (
IN EFI_EVENT Event,
- IN DT_PORT * pPort
+ IN ESL_IO_MGMT * pIo
)
{
UINT32 LengthInBytes;
- DT_PACKET * pCurrentPacket;
- DT_PACKET * pNextPacket;
- DT_PACKET * pPacket;
- DT_SOCKET * pSocket;
- DT_UDP4_CONTEXT * pUdp4;
+ ESL_PORT * pPort;
+ ESL_PACKET * pPacket;
+ ESL_SOCKET * pSocket;
EFI_STATUS Status;
DBG_ENTER ( );
@@ -2267,142 +988,69 @@ EslUdpTxComplete4 ( //
// Locate the active transmit packet
//
+ pPacket = pIo->pPacket;
+ pPort = pIo->pPort;
pSocket = pPort->pSocket;
- pUdp4 = &pPort->Context.Udp4;
- pPacket = pUdp4->pTxPacket;
-
+
//
- // Mark this packet as complete
+ // Get the transmit length and status
//
- pUdp4->pTxPacket = NULL;
LengthInBytes = pPacket->Op.Udp4Tx.TxData.DataLength;
pSocket->TxBytes -= LengthInBytes;
-
- //
- // Save any transmit error
- //
- Status = pUdp4->TxToken.Status;
- if ( EFI_ERROR ( Status )) {
- if ( !EFI_ERROR ( pSocket->TxError )) {
- pSocket->TxError = Status;
- }
- DEBUG (( DEBUG_TX | DEBUG_INFO,
- "ERROR - Transmit failure for packet 0x%08x, Status: %r\r\n",
- pPacket,
- Status ));
-
- //
- // Empty the normal transmit list
- //
- pCurrentPacket = pPacket;
- pNextPacket = pSocket->pTxPacketListHead;
- while ( NULL != pNextPacket ) {
- pPacket = pNextPacket;
- pNextPacket = pPacket->pNext;
- EslSocketPacketFree ( pPacket, DEBUG_TX );
- }
- pSocket->pTxPacketListHead = NULL;
- pSocket->pTxPacketListTail = NULL;
- pPacket = pCurrentPacket;
- }
- else
- {
- DEBUG (( DEBUG_TX | DEBUG_INFO,
- "0x%08x: Packet transmitted %d bytes successfully\r\n",
- pPacket,
- LengthInBytes ));
-
- //
- // Verify the transmit engine is still running
- //
- if ( !pPort->bCloseNow ) {
- //
- // Start the next packet transmission
- //
- EslUdpTxStart4 ( pPort );
- }
- }
-
- //
- // Release this packet
- //
- EslSocketPacketFree ( pPacket, DEBUG_TX );
-
+ Status = pIo->Token.Udp4Tx.Status;
+
//
- // Finish the close operation if necessary
+ // Complete the transmit operation
//
- if (( PORT_STATE_CLOSE_STARTED <= pPort->State )
- && ( NULL == pSocket->pTxPacketListHead )
- && ( NULL == pUdp4->pTxPacket )) {
- //
- // Indicate that the transmit is complete
- //
- EslUdpPortCloseTxDone4 ( pPort );
- }
+ EslSocketTxComplete ( pIo,
+ LengthInBytes,
+ Status,
+ "UDP ",
+ &pSocket->pTxPacketListHead,
+ &pSocket->pTxPacketListTail,
+ &pPort->pTxActive,
+ &pPort->pTxFree );
DBG_EXIT ( );
}
/**
- Transmit data using a network connection.
-
- @param [in] pPort Address of a DT_PORT structure
-
- **/
-VOID
-EslUdpTxStart4 (
- IN DT_PORT * pPort
- )
-{
- DT_PACKET * pNextPacket;
- DT_PACKET * pPacket;
- DT_SOCKET * pSocket;
- DT_UDP4_CONTEXT * pUdp4;
- EFI_UDP4_PROTOCOL * pUdp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Get the packet from the queue head
- //
- pSocket = pPort->pSocket;
- pPacket = pSocket->pTxPacketListHead;
- if ( NULL != pPacket ) {
- //
- // Remove the packet from the queue
- //
- pNextPacket = pPacket->pNext;
- pSocket->pTxPacketListHead = pNextPacket;
- if ( NULL == pNextPacket ) {
- pSocket->pTxPacketListTail = NULL;
- }
-
- //
- // Set the packet as active
- //
- pUdp4 = &pPort->Context.Udp4;
- pUdp4->pTxPacket = pPacket;
-
- //
- // Start the transmit operation
- //
- pUdp4Protocol = pUdp4->pProtocol;
- pUdp4->TxToken.Packet.TxData = &pPacket->Op.Udp4Tx.TxData;
- Status = pUdp4Protocol->Transmit ( pUdp4Protocol, &pUdp4->TxToken );
- if ( EFI_ERROR ( Status )) {
- pSocket = pPort->pSocket;
- if ( EFI_SUCCESS == pSocket->TxError ) {
- pSocket->TxError = Status;
- }
- }
- }
-
- DBG_EXIT ( );
-}
-
+ Interface between the socket layer and the network specific
+ code that supports SOCK_DGRAM sockets over UDPv4.
+**/
+CONST ESL_PROTOCOL_API cEslUdp4Api = {
+ "UDPv4",
+ IPPROTO_UDP,
+ OFFSET_OF ( ESL_PORT, Context.Udp4.ConfigData ),
+ OFFSET_OF ( ESL_LAYER, pUdp4List ),
+ OFFSET_OF ( struct sockaddr_in, sin_zero ),
+ sizeof ( struct sockaddr_in ),
+ AF_INET,
+ sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),
+ sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),
+ OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Rx.Packet.RxData ),
+ FALSE,
+ EADDRINUSE,
+ NULL, // Accept
+ NULL, // ConnectPoll
+ NULL, // ConnectStart
+ EslUdp4SocketIsConfigured,
+ EslUdp4LocalAddressGet,
+ EslUdp4LocalAddressSet,
+ NULL, // Listen
+ NULL, // OptionGet
+ NULL, // OptionSet
+ EslUdp4PacketFree,
+ EslUdp4PortAllocate,
+ NULL, // PortClose,
+ NULL, // PortCloseOp
+ TRUE,
+ EslUdp4Receive,
+ EslUdp4RemoteAddressGet,
+ EslUdp4RemoteAddressSet,
+ EslUdp4RxComplete,
+ NULL, // RxStart
+ EslUdp4TxBuffer,
+ EslUdp4TxComplete,
+ NULL // TxOobComplete
+};
|