From de69fcb842dbefca4da8319c143ed12fa6b12c54 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 9 Jun 2008 06:40:21 -0700 Subject: [PATCH 1/3] RecvFrom() expansion, add flags parameter to some Send calls --- examples/tcp-large-transfer.cc | 2 +- src/applications/packet-sink/packet-sink.cc | 2 +- src/applications/udp-echo/udp-echo-client.cc | 2 +- src/applications/udp-echo/udp-echo-server.cc | 4 +- src/internet-node/tcp-socket-impl.cc | 34 +- src/internet-node/tcp-socket-impl.h | 12 +- src/internet-node/udp-socket-impl.cc | 49 ++- src/internet-node/udp-socket-impl.h | 9 +- src/node/packet-socket.cc | 34 +- src/node/packet-socket.h | 10 +- src/node/socket.cc | 101 +++--- src/node/socket.h | 309 ++++++++++++++----- src/node/tcp-socket.h | 10 +- src/node/udp-socket.h | 9 +- src/routing/olsr/olsr-agent-impl.cc | 2 +- 15 files changed, 410 insertions(+), 179 deletions(-) diff --git a/examples/tcp-large-transfer.cc b/examples/tcp-large-transfer.cc index c715e348a..f648d50ea 100644 --- a/examples/tcp-large-transfer.cc +++ b/examples/tcp-large-transfer.cc @@ -204,7 +204,7 @@ void WriteUntilBufferFull (Ptr localSocket, uint32_t nBytes) char m = toascii (97 + i % 26); data[i] = m; } - uint32_t amountSent = localSocket->Send (data, curSize); + uint32_t amountSent = localSocket->Send (data, curSize, 0); if(amountSent < curSize) { std::cout << "Socket blocking, returning" << std::endl; diff --git a/src/applications/packet-sink/packet-sink.cc b/src/applications/packet-sink/packet-sink.cc index d73ca1f03..1b65bfa85 100644 --- a/src/applications/packet-sink/packet-sink.cc +++ b/src/applications/packet-sink/packet-sink.cc @@ -105,7 +105,7 @@ void PacketSink::HandleRead (Ptr socket) Ptr packet; while (packet = socket->Recv ()) { - SocketRxAddressTag tag; + SocketAddressTag tag; bool found; found = packet->FindFirstMatchingTag (tag); NS_ASSERT (found); diff --git a/src/applications/udp-echo/udp-echo-client.cc b/src/applications/udp-echo/udp-echo-client.cc index 55f5bda6d..9a1efc293 100644 --- a/src/applications/udp-echo/udp-echo-client.cc +++ b/src/applications/udp-echo/udp-echo-client.cc @@ -156,7 +156,7 @@ UdpEchoClient::HandleRead (Ptr socket) Ptr packet; while (packet = socket->Recv ()) { - SocketRxAddressTag tag; + SocketAddressTag tag; bool found; found = packet->FindFirstMatchingTag (tag); NS_ASSERT (found); diff --git a/src/applications/udp-echo/udp-echo-server.cc b/src/applications/udp-echo/udp-echo-server.cc index 3851a88b7..f5bc4c93b 100644 --- a/src/applications/udp-echo/udp-echo-server.cc +++ b/src/applications/udp-echo/udp-echo-server.cc @@ -97,7 +97,7 @@ UdpEchoServer::HandleRead (Ptr socket) Ptr packet; while (packet = socket->Recv ()) { - SocketRxAddressTag tag; + SocketAddressTag tag; bool found; found = packet->FindFirstMatchingTag (tag); NS_ASSERT (found); @@ -110,7 +110,7 @@ UdpEchoServer::HandleRead (Ptr socket) address.GetIpv4()); NS_LOG_LOGIC ("Echoing packet"); - socket->SendTo (packet, from); + socket->SendTo (packet, 0, from); } } } diff --git a/src/internet-node/tcp-socket-impl.cc b/src/internet-node/tcp-socket-impl.cc index 959b793c5..7cd0d246d 100644 --- a/src/internet-node/tcp-socket-impl.cc +++ b/src/internet-node/tcp-socket-impl.cc @@ -346,8 +346,10 @@ TcpSocketImpl::Connect (const Address & address) } return -1; } + +//p here is just data, no headers int -TcpSocketImpl::Send (const Ptr p) //p here is just data, no headers +TcpSocketImpl::Send (Ptr p, uint32_t flags) { NS_LOG_FUNCTION (this << p); if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT) @@ -382,11 +384,6 @@ TcpSocketImpl::Send (const Ptr p) //p here is just data, no headers } } -int TcpSocketImpl::Send (const uint8_t* buf, uint32_t size) -{ - return Send (Create (buf, size)); -} - int TcpSocketImpl::DoSendTo (Ptr p, const Address &address) { NS_LOG_FUNCTION (this << p << address); @@ -420,7 +417,7 @@ int TcpSocketImpl::DoSendTo (Ptr p, Ipv4Address ipv4, uint16_t port) } int -TcpSocketImpl::SendTo (Ptr p, const Address &address) +TcpSocketImpl::SendTo (Ptr p, uint32_t flags, const Address &address) { NS_LOG_FUNCTION (this << address << p); if (!m_connected) @@ -430,7 +427,7 @@ TcpSocketImpl::SendTo (Ptr p, const Address &address) } else { - return Send (p); //drop the address according to BSD manpages + return Send (p, flags); //drop the address according to BSD manpages } } @@ -532,6 +529,23 @@ TcpSocketImpl::GetRxAvailable (void) const return m_rxAvailable; } +Ptr +TcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress) +{ + NS_LOG_FUNCTION (this << maxSize << flags); + Ptr packet = Recv (maxSize, flags); + if (packet != 0) + { + SocketAddressTag tag; + bool found; + found = packet->FindFirstMatchingTag (tag); + NS_ASSERT (found); + fromAddress = tag.GetAddress (); + } + return packet; +} + void TcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) { @@ -1048,7 +1062,7 @@ void TcpSocketImpl::NewRx (Ptr p, m_nextRxSequence += s; // Advance next expected sequence //bytesReceived += s; // Statistics NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence ); - SocketRxAddressTag tag; + SocketAddressTag tag; tag.SetAddress (fromAddress); p->AddTag (tag); //buffer this, it'll be read by call to Recv @@ -1106,7 +1120,7 @@ void TcpSocketImpl::NewRx (Ptr p, i->second = 0; // relase reference to already buffered } // Save for later delivery - SocketRxAddressTag tag; + SocketAddressTag tag; tag.SetAddress (fromAddress); p->AddTag (tag); m_bufferedData[tcpHeader.GetSequenceNumber () ] = p; diff --git a/src/internet-node/tcp-socket-impl.h b/src/internet-node/tcp-socket-impl.h index 8f1f832f5..ca5c5a5d1 100644 --- a/src/internet-node/tcp-socket-impl.h +++ b/src/internet-node/tcp-socket-impl.h @@ -65,14 +65,14 @@ public: virtual int ShutdownSend (void); virtual int ShutdownRecv (void); virtual int Connect(const Address &address); - virtual int Send (Ptr p); - virtual int Send (const uint8_t* buf, uint32_t size); - virtual int SendTo(Ptr p, const Address &address); - virtual uint32_t GetTxAvailable (void) const; virtual int Listen(uint32_t queueLimit); - - virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual uint32_t GetTxAvailable (void) const; + virtual int Send (Ptr p, uint32_t flags); + virtual int SendTo(Ptr p, uint32_t flags, const Address &toAddress); virtual uint32_t GetRxAvailable (void) const; + virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress); private: friend class Tcp; diff --git a/src/internet-node/udp-socket-impl.cc b/src/internet-node/udp-socket-impl.cc index 03b0da18f..5f9872089 100644 --- a/src/internet-node/udp-socket-impl.cc +++ b/src/internet-node/udp-socket-impl.cc @@ -224,9 +224,9 @@ UdpSocketImpl::Listen (uint32_t queueLimit) } int -UdpSocketImpl::Send (Ptr p) +UdpSocketImpl::Send (Ptr p, uint32_t flags) { - NS_LOG_FUNCTION (this << p); + NS_LOG_FUNCTION (this << p << flags); if (!m_connected) { @@ -239,7 +239,7 @@ UdpSocketImpl::Send (Ptr p) int UdpSocketImpl::DoSend (Ptr p) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (this << p); if (m_endPoint == 0) { if (Bind () == -1) @@ -380,19 +380,28 @@ UdpSocketImpl::GetTxAvailable (void) const } int -UdpSocketImpl::SendTo (Ptr p, const Address &address) +UdpSocketImpl::SendTo (Ptr p, uint32_t flags, const Address &address) { - NS_LOG_FUNCTION (this << address << p); + NS_LOG_FUNCTION (this << p << flags << address); InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); Ipv4Address ipv4 = transport.GetIpv4 (); uint16_t port = transport.GetPort (); return DoSendTo (p, ipv4, port); } +uint32_t +UdpSocketImpl::GetRxAvailable (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + // We separately maintain this state to avoid walking the queue + // every time this might be called + return m_rxAvailable; +} + Ptr UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (this << maxSize << flags); if (m_deliveryQueue.empty() ) { return 0; @@ -410,13 +419,21 @@ UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) return p; } -uint32_t -UdpSocketImpl::GetRxAvailable (void) const +Ptr +UdpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress) { - NS_LOG_FUNCTION_NOARGS (); - // We separately maintain this state to avoid walking the queue - // every time this might be called - return m_rxAvailable; + NS_LOG_FUNCTION (this << maxSize << flags); + Ptr packet = Recv (maxSize, flags); + if (packet != 0) + { + SocketAddressTag tag; + bool found; + found = packet->FindFirstMatchingTag (tag); + NS_ASSERT (found); + fromAddress = tag.GetAddress (); + } + return packet; } void @@ -431,7 +448,7 @@ UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize) { Address address = InetSocketAddress (ipv4, port); - SocketRxAddressTag tag; + SocketAddressTag tag; tag.SetAddress (address); packet->AddTag (tag); m_deliveryQueue.push (packet); @@ -638,7 +655,7 @@ UdpSocketImplTest::RunTests (void) // Unicast test m_receivedPacket = Create (); m_receivedPacket2 = Create (); - NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create (123), + NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create (123), 0, InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123); Simulator::Run (); NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); @@ -651,7 +668,7 @@ UdpSocketImplTest::RunTests (void) m_receivedPacket = Create (); m_receivedPacket2 = Create (); - NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create (123), + NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create (123), 0, InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123); Simulator::Run (); NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); @@ -673,7 +690,7 @@ UdpSocketImplTest::RunTests (void) m_receivedPacket = Create (); m_receivedPacket2 = Create (); - NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create (123), + NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create (123), 0, InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123); Simulator::Run (); NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); diff --git a/src/internet-node/udp-socket-impl.h b/src/internet-node/udp-socket-impl.h index f7b185215..46dd51cab 100644 --- a/src/internet-node/udp-socket-impl.h +++ b/src/internet-node/udp-socket-impl.h @@ -58,12 +58,13 @@ public: virtual int ShutdownRecv (void); virtual int Connect(const Address &address); virtual int Listen (uint32_t queueLimit); - virtual int Send (Ptr p); - virtual int SendTo (Ptr p, const Address &address); virtual uint32_t GetTxAvailable (void) const; - - virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual int Send (Ptr p, uint32_t flags); + virtual int SendTo (Ptr p, uint32_t flags, const Address &address); virtual uint32_t GetRxAvailable (void) const; + virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress); private: // Attributes set through UdpSocket base class diff --git a/src/node/packet-socket.cc b/src/node/packet-socket.cc index d4824e36c..4e6bb847c 100644 --- a/src/node/packet-socket.cc +++ b/src/node/packet-socket.cc @@ -230,7 +230,7 @@ PacketSocket::Listen(uint32_t queueLimit) } int -PacketSocket::Send (Ptr p) +PacketSocket::Send (Ptr p, uint32_t flags) { NS_LOG_FUNCTION_NOARGS (); if (m_state == STATE_OPEN || @@ -239,7 +239,7 @@ PacketSocket::Send (Ptr p) m_errno = ERROR_NOTCONN; return -1; } - return SendTo (p, m_destAddr); + return SendTo (p, flags, m_destAddr); } uint32_t @@ -275,7 +275,7 @@ PacketSocket::GetTxAvailable (void) const } int -PacketSocket::SendTo(Ptr p, const Address &address) +PacketSocket::SendTo (Ptr p, uint32_t flags, const Address &address) { NS_LOG_FUNCTION_NOARGS (); PacketSocketAddress ad; @@ -361,7 +361,7 @@ PacketSocket::ForwardUp (Ptr device, Ptr packet, if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize) { - SocketRxAddressTag tag; + SocketAddressTag tag; tag.SetAddress (address); packet->AddTag (tag); m_deliveryQueue.push (packet); @@ -381,6 +381,15 @@ PacketSocket::ForwardUp (Ptr device, Ptr packet, } } +uint32_t +PacketSocket::GetRxAvailable (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + // We separately maintain this state to avoid walking the queue + // every time this might be called + return m_rxAvailable; +} + Ptr PacketSocket::Recv (uint32_t maxSize, uint32_t flags) { @@ -402,13 +411,20 @@ PacketSocket::Recv (uint32_t maxSize, uint32_t flags) return p; } -uint32_t -PacketSocket::GetRxAvailable (void) const +Ptr +PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress) { NS_LOG_FUNCTION_NOARGS (); - // We separately maintain this state to avoid walking the queue - // every time this might be called - return m_rxAvailable; + Ptr packet = Recv (maxSize, flags); + if (packet != 0) + { + SocketAddressTag tag; + bool found; + found = packet->FindFirstMatchingTag (tag); + NS_ASSERT (found); + fromAddress = tag.GetAddress (); + } + return packet; } }//namespace ns3 diff --git a/src/node/packet-socket.h b/src/node/packet-socket.h index f0647ae81..528ca740d 100644 --- a/src/node/packet-socket.h +++ b/src/node/packet-socket.h @@ -93,13 +93,13 @@ public: virtual int ShutdownRecv (void); virtual int Connect(const Address &address); virtual int Listen(uint32_t queueLimit); - virtual int Send (Ptr p); virtual uint32_t GetTxAvailable (void) const; - - virtual int SendTo(Ptr p, const Address &address); - - virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual int Send (Ptr p, uint32_t flags); + virtual int SendTo(Ptr p, uint32_t flags, const Address &toAddress); virtual uint32_t GetRxAvailable (void) const; + virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress); private: void ForwardUp (Ptr device, Ptr packet, diff --git a/src/node/socket.cc b/src/node/socket.cc index 0bdc167a0..e5409ca0b 100644 --- a/src/node/socket.cc +++ b/src/node/socket.cc @@ -40,13 +40,6 @@ Socket::~Socket () NS_LOG_FUNCTION_NOARGS (); } -void -Socket::SetCloseUnblocksCallback (Callback > closeUnblocks) -{ - NS_LOG_FUNCTION_NOARGS (); - m_closeUnblocks = closeUnblocks; -} - Ptr Socket::CreateSocket (Ptr node, TypeId tid) { @@ -110,6 +103,13 @@ Socket::SetRecvCallback (Callback > receivedData) m_receivedData = receivedData; } +int +Socket::Send (Ptr p) +{ + NS_LOG_FUNCTION_NOARGS (); + return Send (p, 0); +} + void Socket::NotifyCloseUnblocks (void) { @@ -125,7 +125,8 @@ int Socket::Listen (uint32_t queueLimit) return 0; //XXX the base class version does nothing } -int Socket::Send (const uint8_t* buf, uint32_t size) +int +Socket::Send (const uint8_t* buf, uint32_t size, uint32_t flags) { NS_LOG_FUNCTION_NOARGS (); Ptr p; @@ -137,24 +138,12 @@ int Socket::Send (const uint8_t* buf, uint32_t size) { p = Create (size); } - return Send (p); -} - -Ptr -Socket::Recv (void) -{ - return Recv (std::numeric_limits::max(), 0); + return Send (p, flags); } int -Socket::Recv (uint8_t* buf, uint32_t size, uint32_t flags) -{ - Ptr p = Recv (size, flags); // read up to "size" bytes - memcpy (buf, p->PeekData (), p->GetSize()); - return p->GetSize (); -} - -int Socket::SendTo (const uint8_t* buf, uint32_t size, const Address &address) +Socket::SendTo (const uint8_t* buf, uint32_t size, uint32_t flags, + const Address &toAddress) { NS_LOG_FUNCTION_NOARGS (); Ptr p; @@ -166,7 +155,48 @@ int Socket::SendTo (const uint8_t* buf, uint32_t size, const Address &address) { p = Create (size); } - return SendTo (p, address); + return SendTo (p, flags, toAddress); +} + +Ptr +Socket::Recv (void) +{ + NS_LOG_FUNCTION_NOARGS (); + return Recv (std::numeric_limits::max(), 0); +} + +int +Socket::Recv (uint8_t* buf, uint32_t size, uint32_t flags) +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr p = Recv (size, flags); // read up to "size" bytes + if (p == 0) + { + return 0; + } + memcpy (buf, p->PeekData (), p->GetSize()); + return p->GetSize (); +} + +Ptr +Socket::RecvFrom (Address &fromAddress) +{ + NS_LOG_FUNCTION_NOARGS (); + return RecvFrom (std::numeric_limits::max(), 0, fromAddress); +} + +int +Socket::RecvFrom (uint8_t* buf, uint32_t size, uint32_t flags, + Address &fromAddress) +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr p = RecvFrom (size, flags, fromAddress); + if (p == 0) + { + return 0; + } + memcpy (buf, p->PeekData (), p->GetSize()); + return p->GetSize (); } void @@ -281,54 +311,54 @@ Socket::NotifyDataRecv (void) * Socket Tags ***************************************************************/ -SocketRxAddressTag::SocketRxAddressTag () +SocketAddressTag::SocketAddressTag () { } void -SocketRxAddressTag::SetAddress (Address addr) +SocketAddressTag::SetAddress (Address addr) { m_address = addr; } Address -SocketRxAddressTag::GetAddress (void) const +SocketAddressTag::GetAddress (void) const { return m_address; } TypeId -SocketRxAddressTag::GetTypeId (void) +SocketAddressTag::GetTypeId (void) { - static TypeId tid = TypeId ("ns3::SocketRxAddressTag") + static TypeId tid = TypeId ("ns3::SocketAddressTag") .SetParent () - .AddConstructor () + .AddConstructor () ; return tid; } TypeId -SocketRxAddressTag::GetInstanceTypeId (void) const +SocketAddressTag::GetInstanceTypeId (void) const { return GetTypeId (); } uint32_t -SocketRxAddressTag::GetSerializedSize (void) const +SocketAddressTag::GetSerializedSize (void) const { return m_address.GetSerializedSize (); } void -SocketRxAddressTag::Serialize (TagBuffer i) const +SocketAddressTag::Serialize (TagBuffer i) const { m_address.Serialize (i); } void -SocketRxAddressTag::Deserialize (TagBuffer i) +SocketAddressTag::Deserialize (TagBuffer i) { m_address.Deserialize (i); } void -SocketRxAddressTag::Print (std::ostream &os) const +SocketAddressTag::Print (std::ostream &os) const { os << "address=" << m_address; } @@ -386,4 +416,5 @@ SocketIpTtlTag::Print (std::ostream &os) const os << "Ttl=" << (uint32_t) m_ttl; } + }//namespace ns3 diff --git a/src/node/socket.h b/src/node/socket.h index 34e018743..a15ad0061 100644 --- a/src/node/socket.h +++ b/src/node/socket.h @@ -92,27 +92,22 @@ public: * \param tid The TypeId of the socket to create */ static Ptr CreateSocket (Ptr node, TypeId tid); - /** * \return the errno associated to the last call which failed in this * socket. Each socket's errno is initialized to zero * when the socket is created. */ virtual enum Socket::SocketErrno GetErrno (void) const = 0; - /** * \returns the node this socket is associated with. */ virtual Ptr GetNode (void) const = 0; - void SetCloseUnblocksCallback (Callback > closeUnblocks); - /** * \param closeCompleted Callback invoked when the close operation is * completed. */ void SetCloseCallback (Callback > closeCompleted); - /** * \param connectionSucceeded this callback is invoked when the * connection request initiated by the user is successfully @@ -165,7 +160,8 @@ public: * user should check this return value to confirm that the * callback is supported. */ - virtual bool SetDataSentCallback (Callback, uint32_t> dataSent); + virtual bool SetDataSentCallback (Callback, + uint32_t> dataSent); /** * \brief Notify application when space in transmit buffer is added * @@ -241,13 +237,27 @@ public: */ virtual int Listen (uint32_t queueLimit) = 0; + /** + * \brief Returns the number of bytes which can be sent in a single call + * to Send. + * + * For datagram sockets, this returns the number of bytes that + * can be passed atomically through the underlying protocol. + * + * For stream sockets, this returns the available space in bytes + * left in the transmit buffer. + */ + virtual uint32_t GetTxAvailable (void) const = 0; + /** * \brief Send data (or dummy data) to the remote host * * This function matches closely in semantics to the send() function * call in the standard C library (libc): * ssize_t send (int s, const void *msg, size_t len, int flags); - * except that the function call is asynchronous. + * except that the send I/O is asynchronous. This is the + * primary Send method at this low-level API and must be implemented + * by subclasses. * * In a typical blocking sockets model, this call would block upon * lack of space to hold the message to be sent. In ns-3 at this @@ -272,96 +282,231 @@ public: * split the Packet (based on information obtained from * GetTxAvailable) and reattempt to send the data. * + * The flags argument is formed by or'ing one or more of the values: + * MSG_OOB process out-of-band data + * MSG_DONTROUTE bypass routing, use direct interface + * These flags are _unsupported_ as of ns-3.1. + * * \param p ns3::Packet to send + * \param flags Socket control flags * \returns the number of bytes accepted for transmission if no error * occurs, and -1 otherwise. - */ - virtual int Send (Ptr p) = 0; - - /** - * \brief Returns the number of bytes which can be sent in a single call - * to Send. - * - * For datagram sockets, this returns the number of bytes that - * can be passed atomically through the underlying protocol. * - * For stream sockets, this returns the available space in bytes - * left in the transmit buffer. + * \see SetSendCallback */ - virtual uint32_t GetTxAvailable (void) const = 0; + virtual int Send (Ptr p, uint32_t flags) = 0; - /** - * \brief Send data (or dummy data) to the remote host - * \param buf A pointer to a raw byte buffer of some data to send. If this - * is 0, we send dummy data whose size is specified by the second parameter - * \param size the number of bytes to copy from the buffer - * - * This is provided so as to have an API which is closer in appearance - * to that of real network or BSD sockets. - */ - int Send (const uint8_t* buf, uint32_t size); - /** * \brief Send data to a specified peer. + * + * This method has similar semantics to Send () but subclasses may + * want to provide checks on socket state, so the implementation is + * pushed to subclasses. + * * \param p packet to send - * \param address IP Address of remote host + * \param flags Socket control flags + * \param toAddress IP Address of remote host * \returns -1 in case of error or the number of bytes copied in the * internal buffer and accepted for transmission. */ - virtual int SendTo (Ptr p, const Address &address) = 0; + virtual int SendTo (Ptr p, uint32_t flags, + const Address &toAddress) = 0; - /** - * \brief Send data to a specified peer. - * \param buf A pointer to a raw byte buffer of some data to send. If this - * is 0, we send dummy data whose size is specified by the third parameter - * \param size the number of bytes to copy from the buffer - * \param address IP Address of remote host - * \returns -1 in case of error or the number of bytes copied in the - * internal buffer and accepted for transmission. - * - * This is provided so as to have an API which is closer in appearance - * to that of real network or BSD sockets. - */ - int SendTo (const uint8_t* buf, uint32_t size, const Address &address); - - /** - * \brief Read a single packet from the socket - * \param maxSize reader will accept packet up to maxSize - * \param flags Socket recv flags - * \returns Ptr of the next in-sequence packet. Returns - * 0 if the socket cannot return a next in-sequence packet conforming - * to the maxSize and flags. - */ - virtual Ptr Recv (uint32_t maxSize, uint32_t flags) = 0; - /** - * \brief Read a single packet from the socket - * - * Overloaded version of Recv(maxSize, flags) with maxSize - * implicitly set to maximum sized integer, and flags set to zero. - * - * \returns Ptr of the next in-sequence packet. Returns - * 0 if the socket cannot return a next in-sequence packet. - */ - Ptr Recv (void); - /** - * \brief Recv data (or dummy data) from the remote host - * \param buf A pointer to a raw byte buffer to write the data to. - * If the underlying packet was carring null (fake) data, this buffer - * will be zeroed up to the length specified by the return value. - * \param size Number of bytes (at most) to copy to buf - * \param flags any flags to pass to the socket - * \returns number of bytes copied into buf - * - * This is provided so as to have an API which is closer in appearance - * to that of real network or BSD sockets. - */ - int Recv (uint8_t* buf, uint32_t size, uint32_t flags); /** * Return number of bytes which can be returned from one or * multiple calls to Recv. * Must be possible to call this method from the Recv callback. */ virtual uint32_t GetRxAvailable (void) const = 0; + + /** + * \brief Read data from the socket + * + * This function matches closely in semantics to the recv() function + * call in the standard C library (libc): + * ssize_t recv (int s, void *buf, size_t len, int flags); + * except that the receive I/O is asynchronous. This is the + * primary Recv method at this low-level API and must be implemented + * by subclasses. + * + * This method is normally used only on a connected socket. + * In a typical blocking sockets model, this call would block until + * at least one byte is returned or the connection closes. + * In ns-3 at this API, the call returns immediately in such a case + * and returns 0 if nothing is available to be read. + * However, an application can set a callback, ns3::SetRecvCallback, + * to be notified of data being available to be read + * (when it conceptually unblocks); this is an asynchronous + * I/O model for recv(). + * + * This variant of Recv() uses class ns3::Packet to encapsulate + * data, rather than providing a raw pointer and length field. + * This allows an ns-3 application to attach tags if desired (such + * as a flow ID) and may allow the simulator to avoid some data + * copies. Despite the appearance of receiving Packets on a stream + * socket, just think of it as a fancy byte buffer with streaming + * semantics. + * + * The semantics depend on the type of socket. For a datagram socket, + * each Recv() returns the data from at most one Send(), and order + * is not necessarily preserved. For a stream socket, the bytes + * are delivered in order, and on-the-wire packet boundaries are + * not preserved. + * + * The flags argument is formed by or'ing one or more of the values: + * MSG_OOB process out-of-band data + * MSG_PEEK peek at incoming message + * These flags are _unsupported_ as of ns-3.1. + * + * Some variants of Recv() are supported as additional API, + * including RecvFrom(), overloaded Recv() without arguments, + * and variants that use raw character buffers. + * + * \param maxSize reader will accept packet up to maxSize + * \param flags Socket control flags + * \returns Ptr of the next in-sequence packet. Returns + * 0 if the socket cannot return a next in-sequence packet conforming + * to the maxSize and flags. + * + * \see SetRecvCallback + */ + virtual Ptr Recv (uint32_t maxSize, uint32_t flags) = 0; + + /** + * \brief Read a single packet from the socket and retrieve the sender + * address. + * + * Calls Recv(maxSize, flags) with maxSize + * implicitly set to maximum sized integer, and flags set to zero. + * + * This method has similar semantics to Recv () but subclasses may + * want to provide checks on socket state, so the implementation is + * pushed to subclasses. + * + * \param maxSize reader will accept packet up to maxSize + * \param flags Socket control flags + * \param fromAddress output parameter that will return the + * address of the sender of the received packet, if any. Remains + * untouched if no packet is received. + * \returns Ptr of the next in-sequence packet. Returns + * 0 if the socket cannot return a next in-sequence packet. + */ + virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress) = 0; + + ///////////////////////////////////////////////////////////////////// + // The remainder of these public methods are overloaded methods // + // or variants of Send() and Recv(), and they are non-virtual // + ///////////////////////////////////////////////////////////////////// + + /** + * \brief Send data (or dummy data) to the remote host + * + * Overloaded version of Send(..., flags) with flags set to zero. + * + * \param p ns3::Packet to send + * \returns the number of bytes accepted for transmission if no error + * occurs, and -1 otherwise. + */ + int Send (Ptr p); + + /** + * \brief Send data (or dummy data) to the remote host + * + * This method is provided so as to have an API which is closer in + * appearance to that of real network or BSD sockets. + * + * \param buf A pointer to a raw byte buffer of some data to send. If + * this buffer is 0, we send dummy data whose size is specified by the + * second parameter + * \param size the number of bytes to copy from the buffer + * \param flags Socket control flags + */ + int Send (const uint8_t* buf, uint32_t size, uint32_t flags); + + + /** + * \brief Send data to a specified peer. + * + * This method is provided so as to have an API which is closer in + * appearance to that of real network or BSD sockets. + * + * \param buf A pointer to a raw byte buffer of some data to send. + * If this is 0, we send dummy data whose size is specified by the + * third parameter + * \param size the number of bytes to copy from the buffer + * \param flags Socket control flags + * \param address IP Address of remote host + * \returns -1 in case of error or the number of bytes copied in the + * internal buffer and accepted for transmission. + * + */ + int SendTo (const uint8_t* buf, uint32_t size, uint32_t flags, + const Address &address); + + /** + * \brief Read a single packet from the socket + * + * Overloaded version of Recv(maxSize, flags) with maxSize + * implicitly set to maximum sized integer, and flags set to zero. + * + * \returns Ptr of the next in-sequence packet. Returns + * 0 if the socket cannot return a next in-sequence packet. + */ + Ptr Recv (void); + + /** + * \brief Recv data (or dummy data) from the remote host + * + * This method is provided so as to have an API which is closer in + * appearance to that of real network or BSD sockets. + * + * If the underlying packet was carring null (fake) data, this buffer + * will be zeroed up to the length specified by the return value. + * + * \param buf A pointer to a raw byte buffer to write the data to. + * \param size Number of bytes (at most) to copy to buf + * \param flags any flags to pass to the socket + * \returns number of bytes copied into buf + */ + int Recv (uint8_t* buf, uint32_t size, uint32_t flags); + + /** + * \brief Read a single packet from the socket and retrieve the sender + * address. + * + * Calls RecvFrom (maxSize, flags, fromAddress) with maxSize + * implicitly set to maximum sized integer, and flags set to zero. + * + * \param maxSize reader will accept packet up to maxSize + * \param flags Socket control flags + * \param fromAddress output parameter that will return the + * address of the sender of the received packet, if any. Remains + * untouched if no packet is received. + * \returns Ptr of the next in-sequence packet. Returns + * 0 if the socket cannot return a next in-sequence packet. + */ + Ptr RecvFrom (Address &fromAddress); + + /** + * \brief Read a single packet from the socket and retrieve the sender + * address. + * + * This method is provided so as to have an API which is closer in + * appearance to that of real network or BSD sockets. + * + * \param buf A pointer to a raw byte buffer to write the data to. + * If the underlying packet was carring null (fake) data, this buffer + * will be zeroed up to the length specified by the return value. + * \param size Number of bytes (at most) to copy to buf + * \param flags any flags to pass to the socket + * \param fromAddress output parameter that will return the + * address of the sender of the received packet, if any. Remains + * untouched if no packet is received. + * \returns number of bytes copied into buf + */ + int RecvFrom (uint8_t* buf, uint32_t size, uint32_t flags, + Address &fromAddress); protected: void NotifyCloseUnblocks (void); @@ -391,13 +536,13 @@ protected: }; /** - * \brief This class implements a tag that carries the source address - * of a packet across the receiving socket interface. + * \brief This class implements a tag that carries an address + * of a packet across the socket interface. */ -class SocketRxAddressTag : public Tag +class SocketAddressTag : public Tag { public: - SocketRxAddressTag (); + SocketAddressTag (); void SetAddress (Address addr); Address GetAddress (void) const; diff --git a/src/node/tcp-socket.h b/src/node/tcp-socket.h index 14ef39c5d..0a813b76b 100644 --- a/src/node/tcp-socket.h +++ b/src/node/tcp-socket.h @@ -58,11 +58,15 @@ public: virtual int ShutdownSend (void) = 0; virtual int ShutdownRecv (void) = 0; virtual int Connect (const Address &address) = 0; - virtual int Send (Ptr p) = 0; virtual uint32_t GetTxAvailable (void) const = 0; - virtual int SendTo (Ptr p, const Address &address) = 0; - virtual Ptr Recv (uint32_t maxSize, uint32_t flags) = 0; + virtual int Send (Ptr p, uint32_t flags) = 0; + virtual int SendTo (Ptr p, uint32_t flags, + const Address &toAddress) = 0; virtual uint32_t GetRxAvailable (void) const = 0; + virtual Ptr Recv (uint32_t maxSize, uint32_t flags) = 0; + virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress) = 0; + private: // Indirect the attribute setting and getting through private virtual methods diff --git a/src/node/udp-socket.h b/src/node/udp-socket.h index 61d3d2685..fa20b885d 100644 --- a/src/node/udp-socket.h +++ b/src/node/udp-socket.h @@ -57,11 +57,14 @@ public: virtual int ShutdownSend (void) = 0; virtual int ShutdownRecv (void) = 0; virtual int Connect (const Address &address) = 0; - virtual int Send (Ptr p) = 0; virtual uint32_t GetTxAvailable (void) const = 0; - virtual int SendTo (Ptr p, const Address &address) = 0; - virtual Ptr Recv (uint32_t maxSize, uint32_t flags) = 0; + virtual int Send (Ptr p, uint32_t flags) = 0; + virtual int SendTo (Ptr p, uint32_t flags, + const Address &toAddress) = 0; virtual uint32_t GetRxAvailable (void) const = 0; + virtual Ptr Recv (uint32_t maxSize, uint32_t flags) = 0; + virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress) = 0; private: // Indirect the attribute setting and getting through private virtual methods diff --git a/src/routing/olsr/olsr-agent-impl.cc b/src/routing/olsr/olsr-agent-impl.cc index b9a9ea7e4..cddaece12 100644 --- a/src/routing/olsr/olsr-agent-impl.cc +++ b/src/routing/olsr/olsr-agent-impl.cc @@ -305,7 +305,7 @@ AgentImpl::RecvOlsr (Ptr socket) Ptr receivedPacket; receivedPacket = socket->Recv (); - SocketRxAddressTag tag; + SocketAddressTag tag; bool found; found = receivedPacket->FindFirstMatchingTag (tag); NS_ASSERT (found); From 9ca1253956ee3b02bed7164975c90a113302d21c Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 9 Jun 2008 07:01:12 -0700 Subject: [PATCH 2/3] Change OLSR to use RecvFrom --- src/routing/olsr/olsr-agent-impl.cc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/routing/olsr/olsr-agent-impl.cc b/src/routing/olsr/olsr-agent-impl.cc index cddaece12..851deef3d 100644 --- a/src/routing/olsr/olsr-agent-impl.cc +++ b/src/routing/olsr/olsr-agent-impl.cc @@ -303,13 +303,8 @@ void AgentImpl::RecvOlsr (Ptr socket) { Ptr receivedPacket; - receivedPacket = socket->Recv (); - - SocketAddressTag tag; - bool found; - found = receivedPacket->FindFirstMatchingTag (tag); - NS_ASSERT (found); - Address sourceAddress = tag.GetAddress (); + Address sourceAddress; + receivedPacket = socket->RecvFrom (sourceAddress); InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress); Ipv4Address senderIfaceAddr = inetSourceAddr.GetIpv4 (); From aebdb9fbfd9c477e748b2e8af72e886eaf43906a Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 9 Jun 2008 20:42:31 -0700 Subject: [PATCH 3/3] Move other applications to RecvFrom () --- src/applications/packet-sink/packet-sink.cc | 9 ++------- src/applications/udp-echo/udp-echo-client.cc | 9 ++------- src/applications/udp-echo/udp-echo-server.cc | 9 ++------- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/applications/packet-sink/packet-sink.cc b/src/applications/packet-sink/packet-sink.cc index 1b65bfa85..73dfda731 100644 --- a/src/applications/packet-sink/packet-sink.cc +++ b/src/applications/packet-sink/packet-sink.cc @@ -103,14 +103,9 @@ void PacketSink::StopApplication() // Called at time specified by Stop void PacketSink::HandleRead (Ptr socket) { Ptr packet; - while (packet = socket->Recv ()) + Address from; + while (packet = socket->RecvFrom (from)) { - SocketAddressTag tag; - bool found; - found = packet->FindFirstMatchingTag (tag); - NS_ASSERT (found); - Address from = tag.GetAddress (); - // XXX packet->RemoveTag (tag); if (InetSocketAddress::IsMatchingType (from)) { InetSocketAddress address = InetSocketAddress::ConvertFrom (from); diff --git a/src/applications/udp-echo/udp-echo-client.cc b/src/applications/udp-echo/udp-echo-client.cc index 9a1efc293..9580b7dbe 100644 --- a/src/applications/udp-echo/udp-echo-client.cc +++ b/src/applications/udp-echo/udp-echo-client.cc @@ -154,14 +154,9 @@ UdpEchoClient::HandleRead (Ptr socket) { NS_LOG_FUNCTION (this << socket); Ptr packet; - while (packet = socket->Recv ()) + Address from; + while (packet = socket->RecvFrom (from)) { - SocketAddressTag tag; - bool found; - found = packet->FindFirstMatchingTag (tag); - NS_ASSERT (found); - Address from = tag.GetAddress (); - // XXX packet->RemoveTag (tag); if (InetSocketAddress::IsMatchingType (from)) { InetSocketAddress address = InetSocketAddress::ConvertFrom (from); diff --git a/src/applications/udp-echo/udp-echo-server.cc b/src/applications/udp-echo/udp-echo-server.cc index f5bc4c93b..502673519 100644 --- a/src/applications/udp-echo/udp-echo-server.cc +++ b/src/applications/udp-echo/udp-echo-server.cc @@ -95,14 +95,9 @@ void UdpEchoServer::HandleRead (Ptr socket) { Ptr packet; - while (packet = socket->Recv ()) + Address from; + while (packet = socket->RecvFrom (from)) { - SocketAddressTag tag; - bool found; - found = packet->FindFirstMatchingTag (tag); - NS_ASSERT (found); - Address from = tag.GetAddress (); - // XXX packet->RemoveTag (tag); if (InetSocketAddress::IsMatchingType (from)) { InetSocketAddress address = InetSocketAddress::ConvertFrom (from);