/** 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 ; }
/** 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; } }
/** Create a socket with initial data SockInitData. @param SockInitData Pointer to the initial data of the socket. @return Pointer to the newly created socket, return NULL when exception occured. **/ SOCKET * SockCreate ( IN SOCK_INIT_DATA *SockInitData ) { SOCKET *Sock; SOCKET *Parent; EFI_STATUS Status; ASSERT ((SockInitData != NULL) && (SockInitData->ProtoHandler != NULL)); ASSERT (SockInitData->Type == SockStream); ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN)); Parent = SockInitData->Parent; if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) { DEBUG ( (EFI_D_ERROR, "SockCreate: Socket parent has " "reached its connection limit with %d ConnCnt and %d BackLog\n", Parent->ConnCnt, Parent->BackLog) ); return NULL; } Sock = AllocateZeroPool (sizeof (SOCKET)); if (NULL == Sock) { DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n")); return NULL; } InitializeListHead (&Sock->Link); InitializeListHead (&Sock->ConnectionList); InitializeListHead (&Sock->ListenTokenList); InitializeListHead (&Sock->RcvTokenList); InitializeListHead (&Sock->SndTokenList); InitializeListHead (&Sock->ProcessingSndTokenList); EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK); Sock->SndBuffer.DataQueue = NetbufQueAlloc (); if (NULL == Sock->SndBuffer.DataQueue) { DEBUG ((EFI_D_ERROR, "SockCreate: No resource to allocate" " SndBuffer for new socket\n")); goto OnError; } Sock->RcvBuffer.DataQueue = NetbufQueAlloc (); if (NULL == Sock->RcvBuffer.DataQueue) { DEBUG ((EFI_D_ERROR, "SockCreate: No resource to allocate " "RcvBuffer for new socket\n")); goto OnError; } Sock->Signature = SOCK_SIGNATURE; Sock->Parent = Parent; Sock->BackLog = SockInitData->BackLog; Sock->ProtoHandler = SockInitData->ProtoHandler; Sock->SndBuffer.HighWater = SockInitData->SndBufferSize; Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize; Sock->Type = SockInitData->Type; Sock->DriverBinding = SockInitData->DriverBinding; Sock->State = SockInitData->State; Sock->CreateCallback = SockInitData->CreateCallback; Sock->DestroyCallback = SockInitData->DestroyCallback; Sock->Context = SockInitData->Context; Sock->SockError = EFI_ABORTED; Sock->SndBuffer.LowWater = SOCK_BUFF_LOW_WATER; Sock->RcvBuffer.LowWater = SOCK_BUFF_LOW_WATER; // // Install protocol on Sock->SockHandle // CopyMem ( &(Sock->NetProtocol.TcpProtocol), SockInitData->Protocol, sizeof (EFI_TCP4_PROTOCOL) ); // // copy the protodata into socket // CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize); Status = gBS->InstallMultipleProtocolInterfaces ( &Sock->SockHandle, &gEfiTcp4ProtocolGuid, &(Sock->NetProtocol.TcpProtocol), NULL ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "SockCreate: Install TCP protocol in " "socket failed with %r\n", Status)); goto OnError; } if (Parent != NULL) { ASSERT (Parent->BackLog > 0); ASSERT (SOCK_IS_LISTENING (Parent)); // // need to add it into Parent->ConnectionList // if the Parent->ConnCnt < Parent->BackLog // Parent->ConnCnt++; DEBUG ( (EFI_D_NET, "SockCreate: Create a new socket and add to parent, now conncnt is %d\n", Parent->ConnCnt) ); InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList); } if (Sock->CreateCallback != NULL) { Status = Sock->CreateCallback (Sock, Sock->Context); if (EFI_ERROR (Status)) { goto OnError; } } return Sock; OnError: if (Sock->SockHandle != NULL) { gBS->UninstallMultipleProtocolInterfaces ( Sock->SockHandle, &gEfiTcp4ProtocolGuid, &(Sock->NetProtocol.TcpProtocol), NULL ); } if (NULL != Sock->SndBuffer.DataQueue) { NetbufQueFree (Sock->SndBuffer.DataQueue); } if (NULL != Sock->RcvBuffer.DataQueue) { NetbufQueFree (Sock->RcvBuffer.DataQueue); } FreePool (Sock); return NULL; }