/** Flush the sndBuffer and rcvBuffer of socket. @param Sock Pointer to the socket. **/ VOID SockConnFlush ( IN OUT SOCKET *Sock ) { SOCKET *Child; ASSERT (Sock != NULL); // // Clear the flag in this socket // Sock->Flag = 0; // // Flush the SndBuffer and RcvBuffer of Sock // NetbufQueFlush (Sock->SndBuffer.DataQueue); NetbufQueFlush (Sock->RcvBuffer.DataQueue); // // Signal the pending token // if (Sock->ConnectionToken != NULL) { SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError); Sock->ConnectionToken = NULL; } if (Sock->CloseToken != NULL) { SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError); Sock->CloseToken = NULL; } SockFlushPendingToken (Sock, &(Sock->ListenTokenList)); SockFlushPendingToken (Sock, &(Sock->RcvTokenList)); SockFlushPendingToken (Sock, &(Sock->SndTokenList)); SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList)); // // Destroy the pending connection, if it is a listening socket // if (SOCK_IS_LISTENING (Sock)) { while (!IsListEmpty (&Sock->ConnectionList)) { Child = NET_LIST_HEAD ( &Sock->ConnectionList, SOCKET, ConnectionList ); SockDestroyChild (Child); } Sock->ConnCnt = 0; } return ; }
/** Cancel the tokens in the specific token list. @param[in] Token Pointer to the Token. If NULL, all tokens in SpecifiedTokenList will be canceled. @param[in, out] SpecifiedTokenList Pointer to the token list to be checked. @retval EFI_SUCCESS Cancel the tokens in the specific token listsuccessfully. @retval EFI_NOT_FOUND The Token is not found in SpecifiedTokenList. **/ EFI_STATUS SockCancelToken ( IN SOCK_COMPLETION_TOKEN *Token, IN OUT LIST_ENTRY *SpecifiedTokenList ) { EFI_STATUS Status; LIST_ENTRY *Entry; SOCK_TOKEN *SockToken; Status = EFI_SUCCESS; Entry = NULL; SockToken = NULL; if (IsListEmpty (SpecifiedTokenList) && Token != NULL) { return EFI_NOT_FOUND; } // // Iterate through the SpecifiedTokenList. // Entry = SpecifiedTokenList->ForwardLink; while (Entry != SpecifiedTokenList) { SockToken = NET_LIST_USER_STRUCT (Entry, SOCK_TOKEN, TokenList); if (Token == NULL) { SIGNAL_TOKEN (SockToken->Token, EFI_ABORTED); RemoveEntryList (&SockToken->TokenList); FreePool (SockToken); Entry = SpecifiedTokenList->ForwardLink; Status = EFI_SUCCESS; } else { if (Token == (VOID *) SockToken->Token) { SIGNAL_TOKEN (Token, EFI_ABORTED); RemoveEntryList (&(SockToken->TokenList)); FreePool (SockToken); return EFI_SUCCESS; } Status = EFI_NOT_FOUND; Entry = Entry->ForwardLink; } } ASSERT (IsListEmpty (SpecifiedTokenList) || Token != NULL); return Status; }
/** Flush the tokens in the specific token list. @param Sock Pointer to the socket. @param PendingTokenList Pointer to the token list to be flushed. **/ VOID SockFlushPendingToken ( IN SOCKET *Sock, IN LIST_ENTRY *PendingTokenList ) { SOCK_TOKEN *SockToken; SOCK_COMPLETION_TOKEN *Token; ASSERT ((Sock != NULL) && (PendingTokenList != NULL)); while (!IsListEmpty (PendingTokenList)) { SockToken = NET_LIST_HEAD ( PendingTokenList, SOCK_TOKEN, TokenList ); Token = SockToken->Token; SIGNAL_TOKEN (Token, Sock->SockError); RemoveEntryList (&(SockToken->TokenList)); FreePool (SockToken); } }
/** Get received data from the socket layer to the receive token. @param Sock Pointer to the socket. @param RcvToken Pointer to the application provided receive token. @return The length of data received in this token. **/ UINT32 SockProcessRcvToken ( IN SOCKET *Sock, IN OUT SOCK_IO_TOKEN *RcvToken ) { UINT32 TokenRcvdBytes; EFI_TCP4_RECEIVE_DATA *RxData; BOOLEAN IsUrg; ASSERT (Sock != NULL); ASSERT (SockStream == Sock->Type); RxData = RcvToken->Packet.RxData; TokenRcvdBytes = SockTcpDataToRcv ( &Sock->RcvBuffer, &IsUrg, (UINT32) RxData->DataLength ); // // Copy data from RcvBuffer of socket to user // provided RxData and set the fields in TCP RxData // SockSetTcpRxData (Sock, RxData, TokenRcvdBytes, IsUrg); NetbufQueTrim (Sock->RcvBuffer.DataQueue, TokenRcvdBytes); SIGNAL_TOKEN (&(RcvToken->Token), EFI_SUCCESS); return TokenRcvdBytes; }
/** Signal the receive token with the specific error or set socket error code after error is received. @param Sock Pointer to the socket. @param Error The error code received. **/ VOID SockRcvdErr ( IN OUT SOCKET *Sock, IN EFI_STATUS Error ) { SOCK_TOKEN *SockToken; if (!IsListEmpty (&Sock->RcvTokenList)) { SockToken = NET_LIST_HEAD ( &Sock->RcvTokenList, SOCK_TOKEN, TokenList ); RemoveEntryList (&SockToken->TokenList); SIGNAL_TOKEN (SockToken->Token, Error); FreePool (SockToken); } else { SOCK_ERROR (Sock, Error); } }
/** Wake up the connection token while the connection is successfully established, then try to process any pending send token. @param[in, out] Sock Pointer to the socket. **/ VOID SockWakeConnToken ( IN OUT SOCKET *Sock ) { ASSERT (Sock->ConnectionToken != NULL); SIGNAL_TOKEN (Sock->ConnectionToken, EFI_SUCCESS); Sock->ConnectionToken = NULL; // // check to see if some pending send token existed? // SockProcessSndToken (Sock); }
/** Called by low layer protocol to indicate that some data is sent or processed. This function trims the sent data in the socket send buffer, signals the data token if proper. @param Sock Pointer to the socket. @param Count The length of the data processed or sent, in bytes. **/ VOID SockDataSent ( IN SOCKET *Sock, IN UINT32 Count ) { SOCK_TOKEN *SockToken; SOCK_COMPLETION_TOKEN *SndToken; ASSERT (!IsListEmpty (&Sock->ProcessingSndTokenList)); ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize); NetbufQueTrim (Sock->SndBuffer.DataQueue, Count); // // To check if we can signal some snd token in this socket // while (Count > 0) { SockToken = NET_LIST_HEAD ( &(Sock->ProcessingSndTokenList), SOCK_TOKEN, TokenList ); SndToken = SockToken->Token; if (SockToken->RemainDataLen <= Count) { RemoveEntryList (&(SockToken->TokenList)); SIGNAL_TOKEN (SndToken, EFI_SUCCESS); Count -= SockToken->RemainDataLen; FreePool (SockToken); } else { SockToken->RemainDataLen -= Count; Count = 0; } } // // to judge if we can process some send token in // Sock->SndTokenList, if so process those send token // SockProcessSndToken (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); } }
/** Wake up the listen token while the connection is established successfully. @param[in, out] Sock Pointer to the socket. **/ VOID SockWakeListenToken ( IN OUT SOCKET *Sock ) { SOCKET *Parent; SOCK_TOKEN *SockToken; EFI_TCP4_LISTEN_TOKEN *ListenToken; Parent = Sock->Parent; ASSERT ((Parent != NULL) && SOCK_IS_LISTENING (Parent) && SOCK_IS_CONNECTED (Sock)); if (!IsListEmpty (&Parent->ListenTokenList)) { SockToken = NET_LIST_HEAD ( &Parent->ListenTokenList, SOCK_TOKEN, TokenList ); ListenToken = (EFI_TCP4_LISTEN_TOKEN *) SockToken->Token; ListenToken->NewChildHandle = Sock->SockHandle; SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS); RemoveEntryList (&SockToken->TokenList); FreePool (SockToken); RemoveEntryList (&Sock->ConnectionList); Parent->ConnCnt--; DEBUG ( (EFI_D_NET, "SockWakeListenToken: accept a socket, now conncnt is %d", Parent->ConnCnt) ); Sock->Parent = NULL; } }
/** Process the send token. @param Sock Pointer to the socket. **/ VOID SockProcessSndToken ( IN OUT SOCKET *Sock ) { UINT32 FreeSpace; SOCK_TOKEN *SockToken; UINT32 DataLen; SOCK_IO_TOKEN *SndToken; EFI_TCP4_TRANSMIT_DATA *TxData; EFI_STATUS Status; ASSERT ((Sock != NULL) && (SockStream == Sock->Type)); FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF); // // to determine if process a send token using // socket layer flow control policy // while ((FreeSpace >= Sock->SndBuffer.LowWater) && !IsListEmpty (&Sock->SndTokenList)) { SockToken = NET_LIST_HEAD ( &(Sock->SndTokenList), SOCK_TOKEN, TokenList ); // // process this token // RemoveEntryList (&(SockToken->TokenList)); InsertTailList ( &(Sock->ProcessingSndTokenList), &(SockToken->TokenList) ); // // Proceess it in the light of SockType // SndToken = (SOCK_IO_TOKEN *) SockToken->Token; TxData = SndToken->Packet.TxData; DataLen = (UINT32) TxData->DataLength; Status = SockProcessTcpSndData (Sock, TxData); if (EFI_ERROR (Status)) { goto OnError; } if (DataLen >= FreeSpace) { FreeSpace = 0; } else { FreeSpace -= DataLen; } } return ; OnError: RemoveEntryList (&SockToken->TokenList); SIGNAL_TOKEN (SockToken->Token, Status); FreePool (SockToken); }