/** Clone a new socket including its associated protocol control block. @param Sock Pointer to the socket to be cloned. @return Pointer to the newly cloned socket. If NULL, error condition occurred. **/ SOCKET * SockClone ( IN SOCKET *Sock ) { SOCKET *ClonedSock; SOCK_INIT_DATA InitData; InitData.BackLog = Sock->BackLog; InitData.Parent = Sock; InitData.State = Sock->State; InitData.ProtoHandler = Sock->ProtoHandler; InitData.Type = Sock->Type; InitData.RcvBufferSize = Sock->RcvBuffer.HighWater; InitData.SndBufferSize = Sock->SndBuffer.HighWater; InitData.DriverBinding = Sock->DriverBinding; InitData.Protocol = &(Sock->NetProtocol); InitData.CreateCallback = Sock->CreateCallback; InitData.DestroyCallback = Sock->DestroyCallback; InitData.Context = Sock->Context; InitData.ProtoData = Sock->ProtoReserved; InitData.DataSize = sizeof (Sock->ProtoReserved); ClonedSock = SockCreate (&InitData); if (NULL == ClonedSock) { DEBUG ((EFI_D_ERROR, "SockClone: no resource to create a cloned sock\n")); return NULL; } SockSetState (ClonedSock, SO_CONNECTING); ClonedSock->ConfigureState = Sock->ConfigureState; return ClonedSock; }
/** Called by the low layer protocol to indicate the socket a connection is established. This function just changes the socket's state to SO_CONNECTED and signals the token used for connection establishment. @param[in, out] Sock Pointer to the socket associated with the established connection. **/ VOID SockConnEstablished ( IN OUT SOCKET *Sock ) { ASSERT (SO_CONNECTING == Sock->State); SockSetState (Sock, SO_CONNECTED); if (NULL == Sock->Parent) { SockWakeConnToken (Sock); } else { SockWakeListenToken (Sock); } }
/** Destroy a socket. @param Sock Pointer to the socket. **/ VOID SockDestroy ( IN OUT SOCKET *Sock ) { ASSERT (SockStream == Sock->Type); // // Flush the completion token buffered // by sock and rcv, snd buffer // if (!SOCK_IS_UNCONFIGURED (Sock)) { SockConnFlush (Sock); SockSetState (Sock, SO_CLOSED); Sock->ConfigureState = SO_UNCONFIGURED; } // // Destroy the RcvBuffer Queue and SendBuffer Queue // NetbufQueFree (Sock->RcvBuffer.DataQueue); NetbufQueFree (Sock->SndBuffer.DataQueue); // // Remove it from parent connection list if needed // if (Sock->Parent != NULL) { RemoveEntryList (&(Sock->ConnectionList)); (Sock->Parent->ConnCnt)--; DEBUG ( (EFI_D_NET, "SockDestroy: Delete a unaccepted socket from parent" "now conncnt is %d\n", Sock->Parent->ConnCnt) ); Sock->Parent = NULL; } FreePool (Sock); return ; }
/** Called by the low layer protocol to indicate the connection is closed. This function flushes the socket, sets the state to SO_CLOSED and signals the close token. @param Sock Pointer to the socket associated with the closed connection. **/ VOID SockConnClosed ( IN OUT SOCKET *Sock ) { if (Sock->CloseToken != NULL) { SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS); Sock->CloseToken = NULL; } SockConnFlush (Sock); SockSetState (Sock, SO_CLOSED); if (Sock->Parent != NULL) { SockDestroyChild (Sock); } }
/** Configure the Pcb using CfgData. @param Sk Pointer to the socket of this TCP instance. @param CfgData Pointer to the TCP configuration data. @retval EFI_SUCCESS The operation is completed successfully. @retval EFI_INVALID_PARAMETER A same access point has been configured in another TCP instance. @retval EFI_OUT_OF_RESOURCES Failed due to resource limit. **/ EFI_STATUS Tcp4ConfigurePcb ( IN SOCKET *Sk, IN EFI_TCP4_CONFIG_DATA *CfgData ) { EFI_IP4_CONFIG_DATA IpCfgData; EFI_STATUS Status; EFI_TCP4_OPTION *Option; TCP4_PROTO_DATA *TcpProto; TCP_CB *Tcb; ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL)); TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved; Tcb = TcpProto->TcpPcb; ASSERT (Tcb != NULL); // // Add Ip for send pkt to the peer // CopyMem (&IpCfgData, &mIp4IoDefaultIpConfigData, sizeof (IpCfgData)); IpCfgData.DefaultProtocol = EFI_IP_PROTO_TCP; IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress; IpCfgData.StationAddress = CfgData->AccessPoint.StationAddress; IpCfgData.SubnetMask = CfgData->AccessPoint.SubnetMask; IpCfgData.ReceiveTimeout = (UINT32) (-1); // // Configure the IP instance this Tcb consumes. // Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData); if (EFI_ERROR (Status)) { goto OnExit; } // // Get the default address info if the instance is configured to use default address. // if (CfgData->AccessPoint.UseDefaultAddress) { CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress; CfgData->AccessPoint.SubnetMask = IpCfgData.SubnetMask; } // // check if we can bind this endpoint in CfgData // Status = Tcp4Bind (&(CfgData->AccessPoint)); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: Bind endpoint failed " "with %r\n", Status)); goto OnExit; } // // Initalize the operating information in this Tcb // ASSERT (Tcb->State == TCP_CLOSED && IsListEmpty (&Tcb->SndQue) && IsListEmpty (&Tcb->RcvQue)); TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE); Tcb->State = TCP_CLOSED; Tcb->SndMss = 536; Tcb->RcvMss = TcpGetRcvMss (Sk); Tcb->SRtt = 0; Tcb->Rto = 3 * TCP_TICK_HZ; Tcb->CWnd = Tcb->SndMss; Tcb->Ssthresh = 0xffffffff; Tcb->CongestState = TCP_CONGEST_OPEN; Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN; Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD; Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE; Tcb->MaxRexmit = TCP_MAX_LOSS; Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME; Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME; Tcb->ConnectTimeout = TCP_CONNECT_TIME; // // initialize Tcb in the light of CfgData // Tcb->Ttl = CfgData->TimeToLive; Tcb->Tos = CfgData->TypeOfService; Tcb->UseDefaultAddr = CfgData->AccessPoint.UseDefaultAddress; CopyMem (&Tcb->LocalEnd.Ip, &CfgData->AccessPoint.StationAddress, sizeof (IP4_ADDR)); Tcb->LocalEnd.Port = HTONS (CfgData->AccessPoint.StationPort); IP4_COPY_ADDRESS (&Tcb->SubnetMask, &CfgData->AccessPoint.SubnetMask); if (CfgData->AccessPoint.ActiveFlag) { CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR)); Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort); } else { Tcb->RemoteEnd.Ip = 0; Tcb->RemoteEnd.Port = 0; } Option = CfgData->ControlOption; if (Option != NULL) { SET_RCV_BUFFSIZE ( Sk, (UINT32) (TCP_COMP_VAL ( TCP_RCV_BUF_SIZE_MIN, TCP_RCV_BUF_SIZE, TCP_RCV_BUF_SIZE, Option->ReceiveBufferSize ) ) ); SET_SND_BUFFSIZE ( Sk, (UINT32) (TCP_COMP_VAL ( TCP_SND_BUF_SIZE_MIN, TCP_SND_BUF_SIZE, TCP_SND_BUF_SIZE, Option->SendBufferSize ) ) ); SET_BACKLOG ( Sk, (UINT32) (TCP_COMP_VAL ( TCP_BACKLOG_MIN, TCP_BACKLOG, TCP_BACKLOG, Option->MaxSynBackLog ) ) ); Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL ( TCP_MAX_LOSS_MIN, TCP_MAX_LOSS, TCP_MAX_LOSS, Option->DataRetries ); Tcb->FinWait2Timeout = TCP_COMP_VAL ( TCP_FIN_WAIT2_TIME, TCP_FIN_WAIT2_TIME_MAX, TCP_FIN_WAIT2_TIME, (UINT32) (Option->FinTimeout * TCP_TICK_HZ) ); if (Option->TimeWaitTimeout != 0) { Tcb->TimeWaitTimeout = TCP_COMP_VAL ( TCP_TIME_WAIT_TIME, TCP_TIME_WAIT_TIME_MAX, TCP_TIME_WAIT_TIME, (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ) ); } else { Tcb->TimeWaitTimeout = 0; } if (Option->KeepAliveProbes != 0) { TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE); Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL ( TCP_MAX_KEEPALIVE_MIN, TCP_MAX_KEEPALIVE, TCP_MAX_KEEPALIVE, Option->KeepAliveProbes ); Tcb->KeepAliveIdle = TCP_COMP_VAL ( TCP_KEEPALIVE_IDLE_MIN, TCP_KEEPALIVE_IDLE_MAX, TCP_KEEPALIVE_IDLE_MIN, (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ) ); Tcb->KeepAlivePeriod = TCP_COMP_VAL ( TCP_KEEPALIVE_PERIOD_MIN, TCP_KEEPALIVE_PERIOD, TCP_KEEPALIVE_PERIOD, (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ) ); } Tcb->ConnectTimeout = TCP_COMP_VAL ( TCP_CONNECT_TIME_MIN, TCP_CONNECT_TIME, TCP_CONNECT_TIME, (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ) ); if (!Option->EnableNagle) { TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE); } if (!Option->EnableTimeStamp) { TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS); } if (!Option->EnableWindowScaling) { TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS); } } // // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is // determined, construct the IP device path and install it. // Status = TcpInstallDevicePath (Sk); if (EFI_ERROR (Status)) { goto OnExit; } // // update state of Tcb and socket // if (!CfgData->AccessPoint.ActiveFlag) { TcpSetState (Tcb, TCP_LISTEN); SockSetState (Sk, SO_LISTENING); Sk->ConfigureState = SO_CONFIGURED_PASSIVE; } else { Sk->ConfigureState = SO_CONFIGURED_ACTIVE; } TcpInsertTcb (Tcb); OnExit: return Status; }
/** Destroy a socket. @param Sock Pointer to the socket. **/ VOID SockDestroy ( IN OUT SOCKET *Sock ) { VOID *SockProtocol; EFI_GUID *ProtocolGuid; EFI_STATUS Status; ASSERT (SockStream == Sock->Type); if (Sock->DestroyCallback != NULL) { Sock->DestroyCallback (Sock, Sock->Context); } // // Flush the completion token buffered // by sock and rcv, snd buffer // if (!SOCK_IS_UNCONFIGURED (Sock)) { SockConnFlush (Sock); SockSetState (Sock, SO_CLOSED); Sock->ConfigureState = SO_UNCONFIGURED; } // // Destory the RcvBuffer Queue and SendBuffer Queue // NetbufQueFree (Sock->RcvBuffer.DataQueue); NetbufQueFree (Sock->SndBuffer.DataQueue); // // Remove it from parent connection list if needed // if (Sock->Parent != NULL) { RemoveEntryList (&(Sock->ConnectionList)); (Sock->Parent->ConnCnt)--; DEBUG ( (EFI_D_INFO, "SockDestory: Delete a unaccepted socket from parent" "now conncnt is %d\n", Sock->Parent->ConnCnt) ); Sock->Parent = NULL; } // // Set the protocol guid and driver binding handle // in the light of Sock->SockType // ProtocolGuid = &gEfiTcp4ProtocolGuid; // // Retrieve the protocol installed on this sock // Status = gBS->OpenProtocol ( Sock->SockHandle, ProtocolGuid, &SockProtocol, Sock->DriverBinding, Sock->SockHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "SockDestroy: Open protocol installed " "on socket failed with %r\n", Status)); goto FreeSock; } // // Uninstall the protocol installed on this sock // in the light of Sock->SockType // gBS->UninstallMultipleProtocolInterfaces ( Sock->SockHandle, ProtocolGuid, SockProtocol, NULL ); FreeSock: FreePool (Sock); return ; }