diff --git a/examples/tcp-large-transfer.cc b/examples/tcp-large-transfer.cc index cd304fc57..4bc3b4254 100644 --- a/examples/tcp-large-transfer.cc +++ b/examples/tcp-large-transfer.cc @@ -165,7 +165,7 @@ int main (int argc, char *argv[]) // /////////////////////////////////////////////////////////////////////////// - int nBytes = 2000000; + int nBytes = 2000; uint16_t servPort = 50000; // Create a packet sink to receive these packets diff --git a/src/internet-node/tcp-socket.cc b/src/internet-node/tcp-socket.cc index b1635c052..6d1ab4fcf 100644 --- a/src/internet-node/tcp-socket.cc +++ b/src/internet-node/tcp-socket.cc @@ -282,13 +282,25 @@ TcpSocket::ShutdownSend (void) { NS_LOG_FUNCTION_NOARGS (); m_shutdownSend = true; + if (m_state == CLOSED) + { + return -1; + } + if (m_pendingData && m_pendingData->Size() != 0) + { // App shutdown with pending data must wait until all data transmitted + m_closeOnEmpty = true; + NS_LOG_LOGIC("TcpSocket "<Size() != 0) { // App close with pending data must wait until all data transmitted m_closeOnEmpty = true; - NS_LOG_LOGIC("Socket " << this << + NS_LOG_LOGIC("TcpSocket " << this << " deferring close, state " << m_state); return 0; } @@ -955,8 +967,12 @@ bool TcpSocket::SendPendingData (bool withAck) m_endPoint->GetLocalAddress (), m_remoteAddress); m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT - // Notify the application + // Notify the application data was sent Simulator::ScheduleNow(&TcpSocket::NotifyDataSent, this, p->GetSize ()); + if (m_state == FIN_WAIT_1) + { + Simulator::ScheduleNow(&TcpSocket::NotifyCloseUnblocks, this); + } nPacketsSent++; // Count sent this loop m_nextTxSequence += sz; // Advance next tx sequence // Note the high water mark diff --git a/src/node/socket.cc b/src/node/socket.cc index 528ea79a9..1451e413a 100644 --- a/src/node/socket.cc +++ b/src/node/socket.cc @@ -33,6 +33,13 @@ Socket::~Socket () NS_LOG_FUNCTION_NOARGS (); } +void +Socket::SetCloseUnblocksCallback (Callback > closeUnblocks) +{ + NS_LOG_FUNCTION_NOARGS (); + m_closeUnblocks = closeUnblocks; +} + void Socket::SetCloseCallback (Callback > closeCompleted) { @@ -91,6 +98,15 @@ int Socket::Listen (uint32_t queueLimit) return 0; //XXX the base class version does nothing } +void +Socket::NotifyCloseUnblocks (void) +{ + NS_LOG_FUNCTION_NOARGS (); + if (!m_closeUnblocks.IsNull ()) + { + m_closeUnblocks (this); + } +} int Socket::Send (const uint8_t* buf, uint32_t size) { diff --git a/src/node/socket.h b/src/node/socket.h index 921070f77..e840651a4 100644 --- a/src/node/socket.h +++ b/src/node/socket.h @@ -78,6 +78,8 @@ public: */ virtual Ptr GetNode (void) const = 0; + void SetCloseUnblocksCallback (Callback > closeUnblocks); + /** * \param closeCompleted Callback invoked when the close operation is * completed. @@ -316,6 +318,7 @@ public: virtual uint32_t GetRcvBuf (void) = 0; protected: + void NotifyCloseUnblocks (void); void NotifyCloseCompleted (void); void NotifyConnectionSucceeded (void); void NotifyConnectionFailed (void); @@ -327,6 +330,7 @@ protected: void NotifySend (uint32_t spaceAvailable); void NotifyDataRecv (void); + Callback > m_closeUnblocks; Callback > m_closeCompleted; Callback > m_connectionSucceeded; Callback > m_connectionFailed;