--- a/src/internet-node/tcp-socket.cc Thu May 15 21:35:55 2008 -0700
+++ b/src/internet-node/tcp-socket.cc Thu May 15 23:06:58 2008 -0700
@@ -378,11 +378,12 @@
{
NS_LOG_FUNCTION (this << buf << size);
if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
- { // Ok to buffer some data to send
+ {
if (size > GetTxAvailable ())
{
- size = std::min(size, GetTxAvailable() ); //only buffer what can fit
m_wouldBlock = true;
+ m_errno = ERROR_MSGSIZE;
+ return -1;
}
if (!m_pendingData)
{
--- a/src/internet-node/udp-socket.cc Thu May 15 21:35:55 2008 -0700
+++ b/src/internet-node/udp-socket.cc Thu May 15 23:06:58 2008 -0700
@@ -37,6 +37,8 @@
namespace ns3 {
+static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
+
TypeId
UdpSocket::GetTypeId (void)
{
@@ -302,6 +304,12 @@
return -1;
}
+ if (p->GetSize () > GetTxAvailable () )
+ {
+ m_errno = ERROR_MSGSIZE;
+ return -1;
+ }
+
uint32_t localIfIndex;
Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
@@ -344,12 +352,15 @@
return 0;
}
+// XXX maximum message size for UDP broadcast is limited by MTU
+// size of underlying link; we are not checking that now.
uint32_t
UdpSocket::GetTxAvailable (void) const
{
NS_LOG_FUNCTION_NOARGS ();
- // No finite send buffer is modelled
- return std::numeric_limits<uint32_t>::max ();
+ // No finite send buffer is modelled, but we must respect
+ // the maximum size of an IP datagram (65535 bytes - headers).
+ return MAX_IPV4_UDP_DATAGRAM_SIZE;
}
int
--- a/src/node/packet-socket.cc Thu May 15 21:35:55 2008 -0700
+++ b/src/node/packet-socket.cc Thu May 15 23:06:58 2008 -0700
@@ -240,11 +240,12 @@
return SendTo (p, m_destAddr);
}
+// XXX must limit it to interface MTU
uint32_t
PacketSocket::GetTxAvailable (void) const
{
- // No finite send buffer is modelled
- return 0xffffffff;
+ // Use 65536 for now
+ return 0xffff;
}
int
@@ -277,6 +278,11 @@
m_errno = ERROR_AFNOSUPPORT;
return -1;
}
+ if (p->GetSize () > GetTxAvailable ())
+ {
+ m_errno = ERROR_MSGSIZE;
+ return -1;
+ }
ad = PacketSocketAddress::ConvertFrom (address);
bool error = false;
--- a/src/node/socket.h Thu May 15 21:35:55 2008 -0700
+++ b/src/node/socket.h Thu May 15 23:06:58 2008 -0700
@@ -257,15 +257,50 @@
/**
* \brief Send data (or dummy data) to the remote host
- * \param p packet to send
- * \returns -1 in case of error or the number of bytes copied in the
- * internal buffer and accepted for transmission.
+ *
+ * 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.
+ *
+ * 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
+ * API, the call returns immediately in such a case, but the callback
+ * registered with SetSendCallback() is invoked when the socket
+ * has space (when it conceptually unblocks); this is an asynchronous
+ * I/O model for send().
+ *
+ * This variant of Send() 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 sending Packets on a stream
+ * socket, just think of it as a fancy byte buffer with streaming
+ * semantics.
+ *
+ * If either the message buffer within the Packet is too long to pass
+ * atomically through the underlying protocol (for datagram sockets),
+ * or the message buffer cannot entirely fit in the transmit buffer
+ * (for stream sockets), -1 is returned and SocketErrno is set
+ * to ERROR_MSGSIZE. If the packet does not fit, the caller can
+ * split the Packet (based on information obtained from
+ * GetTxAvailable) and reattempt to send the data.
+ *
+ * \param p ns3::Packet to send
+ * \returns the number of bytes accepted for transmission if no error
+ * occurs, and -1 otherwise.
*/
virtual int Send (Ptr<Packet> p) = 0;
/**
- * returns the number of bytes which can be sent in a single call
+ * \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;