Check whether to send data/SYN/FIN and piggyback an ACK. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance. @param[in] Force If TRUE, ignore the sender's SWS avoidance algorithm and send out data by force. @return The number of bytes sent. **/
| 795 | |
| 796 | **/ |
| 797 | INTN |
| 798 | TcpToSendData ( |
| 799 | IN OUT TCP_CB *Tcb, |
| 800 | IN INTN Force |
| 801 | ) |
| 802 | { |
| 803 | UINT32 Len; |
| 804 | INTN Sent; |
| 805 | UINT8 Flag; |
| 806 | NET_BUF *Nbuf; |
| 807 | TCP_SEG *Seg; |
| 808 | TCP_SEQNO Seq; |
| 809 | TCP_SEQNO End; |
| 810 | |
| 811 | ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL) && (Tcb->State != TCP_LISTEN)); |
| 812 | |
| 813 | Sent = 0; |
| 814 | |
| 815 | if ((Tcb->State == TCP_CLOSED) || TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT)) { |
| 816 | |
| 817 | return 0; |
| 818 | } |
| 819 | |
| 820 | do { |
| 821 | // |
| 822 | // Compute how much data can be sent |
| 823 | // |
| 824 | Len = TcpDataToSend (Tcb, Force); |
| 825 | Seq = Tcb->SndNxt; |
| 826 | |
| 827 | ASSERT ((Tcb->State) < (ARRAY_SIZE (mTcpOutFlag))); |
| 828 | Flag = mTcpOutFlag[Tcb->State]; |
| 829 | |
| 830 | if ((Flag & TCP_FLG_SYN) != 0) { |
| 831 | |
| 832 | Seq = Tcb->Iss; |
| 833 | Len = 0; |
| 834 | } |
| 835 | |
| 836 | // |
| 837 | // Only send a segment without data if SYN or |
| 838 | // FIN is set. |
| 839 | // |
| 840 | if ((Len == 0) && ((Flag & (TCP_FLG_SYN | TCP_FLG_FIN)) == 0)) { |
| 841 | return Sent; |
| 842 | } |
| 843 | |
| 844 | Nbuf = TcpGetSegment (Tcb, Seq, Len); |
| 845 | |
| 846 | if (Nbuf == NULL) { |
| 847 | DEBUG ( |
| 848 | (EFI_D_ERROR, |
| 849 | "TcpToSendData: failed to get a segment for TCB %p\n", |
| 850 | Tcb) |
| 851 | ); |
| 852 | |
| 853 | goto OnError; |
| 854 | } |
no test coverage detected