/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* based on tcp-socket-impl.cc, Author: Raj Bhattacharjea <raj.b@gatech.edu>
* Author: Florian Westphal <fw@strlen.de>
*/
#define NS_LOG_APPEND_CONTEXT \
if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_node->GetId () << "] "; }
#include "ns3/node.h"
#include "ns3/inet-socket-address.h"
#include "ns3/log.h"
#include "ns3/ipv4.h"
#include "ipv4-end-point.h"
#include "nsc-tcp-l4-protocol.h"
#include "nsc-tcp-socket-impl.h"
#include "ns3/simulation-singleton.h"
#include "ns3/simulator.h"
#include "ns3/packet.h"
#include "ns3/uinteger.h"
#include "ns3/trace-source-accessor.h"
#include <algorithm>
// for ntohs().
#include <arpa/inet.h>
#include <netinet/in.h>
#include "sim_interface.h"
#include "sim_errno.h"
NS_LOG_COMPONENT_DEFINE ("NscTcpSocketImpl");
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (NscTcpSocketImpl);
TypeId
NscTcpSocketImpl::GetTypeId ()
{
static TypeId tid = TypeId ("ns3::NscTcpSocketImpl")
.SetParent<TcpSocket> ()
.AddTraceSource ("CongestionWindow",
"The TCP connection's congestion window",
MakeTraceSourceAccessor (&NscTcpSocketImpl::m_cWnd))
.AddTraceSource ("SlowStartThreshold",
"TCP slow start threshold (bytes)",
MakeTraceSourceAccessor (&NscTcpSocketImpl::m_ssThresh))
;
return tid;
}
NscTcpSocketImpl::NscTcpSocketImpl ()
: m_endPoint (0),
m_node (0),
m_tcp (0),
m_localAddress (Ipv4Address::GetZero ()),
m_localPort (0),
m_peerAddress ("0.0.0.0", 0),
m_errno (ERROR_NOTERROR),
m_shutdownSend (false),
m_shutdownRecv (false),
m_connected (false),
m_state (CLOSED),
m_closeOnEmpty (false),
m_txBufferSize (0),
m_lastMeasuredRtt (Seconds (0.0))
{
NS_LOG_FUNCTION (this);
}
NscTcpSocketImpl::NscTcpSocketImpl(const NscTcpSocketImpl& sock)
: TcpSocket (sock), //copy the base class callbacks
m_delAckMaxCount (sock.m_delAckMaxCount),
m_delAckTimeout (sock.m_delAckTimeout),
m_noDelay (sock.m_noDelay),
m_endPoint (0),
m_node (sock.m_node),
m_tcp (sock.m_tcp),
m_remoteAddress (sock.m_remoteAddress),
m_remotePort (sock.m_remotePort),
m_localAddress (sock.m_localAddress),
m_localPort (sock.m_localPort),
m_peerAddress (sock.m_peerAddress),
m_errno (sock.m_errno),
m_shutdownSend (sock.m_shutdownSend),
m_shutdownRecv (sock.m_shutdownRecv),
m_connected (sock.m_connected),
m_state (sock.m_state),
m_closeOnEmpty (sock.m_closeOnEmpty),
m_txBufferSize (sock.m_txBufferSize),
m_segmentSize (sock.m_segmentSize),
m_rxWindowSize (sock.m_rxWindowSize),
m_advertisedWindowSize (sock.m_advertisedWindowSize),
m_cWnd (sock.m_cWnd),
m_ssThresh (sock.m_ssThresh),
m_initialCWnd (sock.m_initialCWnd),
m_initialSsThresh (sock.m_initialSsThresh),
m_lastMeasuredRtt (Seconds (0.0)),
m_cnTimeout (sock.m_cnTimeout),
m_cnCount (sock.m_cnCount),
m_rxAvailable (0),
m_nscTcpSocket (0),
m_sndBufSize (sock.m_sndBufSize)
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_LOGIC ("Invoked the copy constructor");
//copy the pending data if necessary
if(!sock.m_txBuffer.empty () )
{
m_txBuffer = sock.m_txBuffer;
}
//can't "copy" the endpoint just yes, must do this when we know the peer info
//too; this is in SYN_ACK_TX
}
NscTcpSocketImpl::~NscTcpSocketImpl ()
{
NS_LOG_FUNCTION (this);
m_node = 0;
if (m_endPoint != 0)
{
NS_ASSERT (m_tcp != 0);
/**
* Note that this piece of code is a bit tricky:
* when DeAllocate is called, it will call into
* Ipv4EndPointDemux::Deallocate which triggers
* a delete of the associated endPoint which triggers
* in turn a call to the method NscTcpSocketImpl::Destroy below
* will will zero the m_endPoint field.
*/
NS_ASSERT (m_endPoint != 0);
m_tcp->DeAllocate (m_endPoint);
NS_ASSERT (m_endPoint == 0);
}
m_tcp = 0;
}
void
NscTcpSocketImpl::SetNode (Ptr<Node> node)
{
m_node = node;
// Initialize some variables
m_cWnd = m_initialCWnd * m_segmentSize;
m_ssThresh = m_initialSsThresh;
m_rxWindowSize = m_advertisedWindowSize;
}
void
NscTcpSocketImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
{
m_nscTcpSocket = tcp->m_nscStack->new_tcp_socket ();
m_tcp = tcp;
}
enum Socket::SocketErrno
NscTcpSocketImpl::GetErrno (void) const
{
NS_LOG_FUNCTION_NOARGS ();
return m_errno;
}
enum Socket::SocketType
NscTcpSocketImpl::GetSocketType (void) const
{
return NS3_SOCK_STREAM;
}
Ptr<Node>
NscTcpSocketImpl::GetNode (void) const
{
NS_LOG_FUNCTION_NOARGS ();
return m_node;
}
void
NscTcpSocketImpl::Destroy (void)
{
NS_LOG_FUNCTION_NOARGS ();
m_node = 0;
m_endPoint = 0;
m_tcp = 0;
}
int
NscTcpSocketImpl::FinishBind (void)
{
NS_LOG_FUNCTION_NOARGS ();
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
m_localAddress = m_endPoint->GetLocalAddress ();
m_localPort = m_endPoint->GetLocalPort ();
return 0;
}
int
NscTcpSocketImpl::Bind (void)
{
NS_LOG_FUNCTION_NOARGS ();
m_endPoint = m_tcp->Allocate ();
return FinishBind ();
}
int
NscTcpSocketImpl::Bind6 ()
{
NS_LOG_LOGIC ("NscTcpSocketImpl: ERROR_AFNOSUPPORT - Bind6 not supported");
m_errno = ERROR_AFNOSUPPORT;
return (-1);
}
int
NscTcpSocketImpl::Bind (const Address &address)
{
NS_LOG_FUNCTION (this<<address);
if (!InetSocketAddress::IsMatchingType (address))
{
return ERROR_INVAL;
}
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
if (ipv4 == Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_tcp->Allocate ();
NS_LOG_LOGIC ("NscTcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
}
else if (ipv4 == Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_tcp->Allocate (port);
NS_LOG_LOGIC ("NscTcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
}
else if (ipv4 != Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_tcp->Allocate (ipv4);
NS_LOG_LOGIC ("NscTcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
}
else if (ipv4 != Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_tcp->Allocate (ipv4, port);
NS_LOG_LOGIC ("NscTcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
}
m_localPort = port;
return FinishBind ();
}
int
NscTcpSocketImpl::ShutdownSend (void)
{
NS_LOG_FUNCTION_NOARGS ();
m_shutdownSend = true;
return 0;
}
int
NscTcpSocketImpl::ShutdownRecv (void)
{
NS_LOG_FUNCTION_NOARGS ();
m_shutdownRecv = true;
return 0;
}
int
NscTcpSocketImpl::Close (void)
{
NS_LOG_FUNCTION (this << m_state);
if (m_state == CLOSED)
{
return -1;
}
if (!m_txBuffer.empty ())
{ // App close with pending data must wait until all data transmitted
m_closeOnEmpty = true;
NS_LOG_LOGIC ("Socket " << this <<
" deferring close, state " << m_state);
return 0;
}
NS_LOG_LOGIC ("NscTcp socket " << this << " calling disconnect(); moving to CLOSED");
m_nscTcpSocket->disconnect ();
m_state = CLOSED;
ShutdownSend ();
return 0;
}
int
NscTcpSocketImpl::Connect (const Address & address)
{
NS_LOG_FUNCTION (this << address);
if (m_endPoint == 0)
{
if (Bind () == -1)
{
NS_ASSERT (m_endPoint == 0);
return -1;
}
NS_ASSERT (m_endPoint != 0);
}
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
m_remoteAddress = transport.GetIpv4 ();
m_remotePort = transport.GetPort ();
std::ostringstream ss;
m_remoteAddress.Print (ss);
std::string ipstring = ss.str ();
m_nscTcpSocket->connect (ipstring.c_str (), m_remotePort);
m_state = SYN_SENT;
return 0;
}
int
NscTcpSocketImpl::Send (const Ptr<Packet> p, uint32_t flags)
{
NS_LOG_FUNCTION (this << p);
NS_ASSERT (p->GetSize () > 0);
if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
{
if (p->GetSize () > GetTxAvailable ())
{
m_errno = ERROR_MSGSIZE;
return -1;
}
uint32_t sent = p->GetSize ();
if (m_state == ESTABLISHED)
{
m_txBuffer.push (p);
m_txBufferSize += sent;
SendPendingData ();
}
else
{ // SYN_SET -- Queue Data
m_txBuffer.push (p);
m_txBufferSize += sent;
}
return sent;
}
else
{
m_errno = ERROR_NOTCONN;
return -1;
}
}
int
NscTcpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
{
NS_LOG_FUNCTION (this << address << p);
if (!m_connected)
{
m_errno = ERROR_NOTCONN;
return -1;
}
else
{
return Send (p, flags); //drop the address according to BSD manpages
}
}
uint32_t
NscTcpSocketImpl::GetTxAvailable (void) const
{
NS_LOG_FUNCTION_NOARGS ();
if (m_txBufferSize != 0)
{
NS_ASSERT (m_txBufferSize <= m_sndBufSize);
return m_sndBufSize - m_txBufferSize;
}
else
{
return m_sndBufSize;
}
}
int
NscTcpSocketImpl::Listen (void)
{
NS_LOG_FUNCTION (this);
m_nscTcpSocket->listen (m_localPort);
m_state = LISTEN;
return 0;
}
void
NscTcpSocketImpl::NSCWakeup ()
{
switch (m_state) {
case SYN_SENT:
if (!m_nscTcpSocket->is_connected ())
break;
m_state = ESTABLISHED;
Simulator::ScheduleNow (&NscTcpSocketImpl::ConnectionSucceeded, this);
// fall through to schedule read/write events
case ESTABLISHED:
if (!m_txBuffer.empty ())
Simulator::ScheduleNow (&NscTcpSocketImpl::SendPendingData, this);
Simulator::ScheduleNow (&NscTcpSocketImpl::ReadPendingData, this);
break;
case LISTEN:
Simulator::ScheduleNow (&NscTcpSocketImpl::Accept, this);
break;
case CLOSED: break;
default:
NS_LOG_DEBUG (this << " invalid state: " << m_state);
}
}
Ptr<Packet>
NscTcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
{
NS_LOG_FUNCTION_NOARGS ();
if (m_deliveryQueue.empty () )
{
m_errno = ERROR_AGAIN;
return 0;
}
Ptr<Packet> p = m_deliveryQueue.front ();
if (p->GetSize () <= maxSize)
{
m_deliveryQueue.pop ();
m_rxAvailable -= p->GetSize ();
}
else
{
m_errno = ERROR_AGAIN;
p = 0;
}
return p;
}
Ptr<Packet>
NscTcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
Address &fromAddress)
{
NS_LOG_FUNCTION (this << maxSize << flags);
Ptr<Packet> packet = Recv (maxSize, flags);
if (packet != 0)
{
SocketAddressTag tag;
bool found;
found = packet->PeekPacketTag (tag);
NS_ASSERT (found);
fromAddress = tag.GetAddress ();
}
return packet;
}
int
NscTcpSocketImpl::GetSockName (Address &address) const
{
NS_LOG_FUNCTION_NOARGS ();
address = InetSocketAddress (m_localAddress, m_localPort);
return 0;
}
uint32_t
NscTcpSocketImpl::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;
}
void
NscTcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
Ptr<Ipv4Interface> incomingInterface)
{
NSCWakeup ();
}
void NscTcpSocketImpl::CompleteFork (void)
{
// The address pairs (m_localAddress, m_localPort, m_remoteAddress, m_remotePort)
// are bogus, but this isn't important at the moment, because
// address <-> Socket handling is done by NSC internally.
// We only need to add the new ns-3 socket to the list of sockets, so
// we use plain Allocate() instead of Allocate(m_localAddress, ... )
struct sockaddr_in sin;
size_t sin_len = sizeof(sin);
if (0 == m_nscTcpSocket->getpeername ((struct sockaddr*) &sin, &sin_len)) {
m_remotePort = ntohs (sin.sin_port);
m_remoteAddress = Ipv4Address::Deserialize ((const uint8_t*) &sin.sin_addr);
m_peerAddress = InetSocketAddress (m_remoteAddress, m_remotePort);
}
m_endPoint = m_tcp->Allocate ();
//the cloned socket with be in listen state, so manually change state
NS_ASSERT (m_state == LISTEN);
m_state = ESTABLISHED;
sin_len = sizeof(sin);
if (0 == m_nscTcpSocket->getsockname ((struct sockaddr *) &sin, &sin_len))
m_localAddress = Ipv4Address::Deserialize ((const uint8_t*) &sin.sin_addr);
NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " accepted connection from "
<< m_remoteAddress << ":" << m_remotePort
<< " to " << m_localAddress << ":" << m_localPort);
//equivalent to FinishBind
m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
NotifyNewConnectionCreated (this, m_peerAddress);
}
void NscTcpSocketImpl::ConnectionSucceeded ()
{ // We would preferred to have scheduled an event directly to
// NotifyConnectionSucceeded, but (sigh) these are protected
// and we can get the address of it :(
struct sockaddr_in sin;
size_t sin_len = sizeof(sin);
if (0 == m_nscTcpSocket->getsockname ((struct sockaddr *) &sin, &sin_len)) {
m_localAddress = Ipv4Address::Deserialize ((const uint8_t*)&sin.sin_addr);
m_localPort = ntohs (sin.sin_port);
}
NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " connected to "
<< m_remoteAddress << ":" << m_remotePort
<< " from " << m_localAddress << ":" << m_localPort);
NotifyConnectionSucceeded ();
}
bool NscTcpSocketImpl::Accept (void)
{
if (m_state == CLOSED)
{ // Happens if application closes listening socket after Accept() was scheduled.
return false;
}
NS_ASSERT (m_state == LISTEN);
if (!m_nscTcpSocket->is_listening ())
{
return false;
}
INetStreamSocket *newsock;
int res = m_nscTcpSocket->accept (&newsock);
if (res != 0)
{
return false;
}
// We could obtain a fromAddress using getpeername, but we've already
// finished the tcp handshake here, i.e. this is a new connection
// and not a connection request.
// if (!NotifyConnectionRequest(fromAddress))
// return true;
// Clone the socket
Ptr<NscTcpSocketImpl> newSock = Copy ();
newSock->m_nscTcpSocket = newsock;
NS_LOG_LOGIC ("Cloned a NscTcpSocketImpl " << newSock);
Simulator::ScheduleNow (&NscTcpSocketImpl::CompleteFork, newSock);
return true;
}
bool NscTcpSocketImpl::ReadPendingData (void)
{
if (m_state != ESTABLISHED)
{
return false;
}
int len, err;
uint8_t buffer[8192];
len = sizeof(buffer);
m_errno = ERROR_NOTERROR;
err = m_nscTcpSocket->read_data (buffer, &len);
if (err == 0 && len == 0)
{
NS_LOG_LOGIC ("ReadPendingData got EOF from socket");
m_state = CLOSE_WAIT;
return false;
}
m_errno = GetNativeNs3Errno (err);
switch (m_errno)
{
case ERROR_NOTERROR: break; // some data was sent
case ERROR_AGAIN: return false;
default:
NS_LOG_WARN ("Error (" << err << ") " <<
"during read_data, ns-3 errno set to" << m_errno);
m_state = CLOSED;
return false;
}
Ptr<Packet> p = Create<Packet> (buffer, len);
SocketAddressTag tag;
tag.SetAddress (m_peerAddress);
p->AddPacketTag (tag);
m_deliveryQueue.push (p);
m_rxAvailable += p->GetSize ();
NotifyDataRecv ();
return true;
}
bool NscTcpSocketImpl::SendPendingData (void)
{
NS_LOG_FUNCTION (this);
NS_LOG_LOGIC ("ENTERING SendPendingData");
if (m_txBuffer.empty ())
{
return false;
}
int ret;
size_t size, written = 0;
do {
NS_ASSERT (!m_txBuffer.empty ());
Ptr<Packet> &p = m_txBuffer.front ();
size = p->GetSize ();
NS_ASSERT (size > 0);
m_errno = ERROR_NOTERROR;
uint8_t *buf = new uint8_t[size];
p->CopyData (buf, size);
ret = m_nscTcpSocket->send_data ((const char *)buf, size);
delete[] buf;
if (ret <= 0)
{
break;
}
written += ret;
NS_ASSERT (m_txBufferSize >= (size_t)ret);
m_txBufferSize -= ret;
if ((size_t)ret < size)
{
p->RemoveAtStart (ret);
break;
}
m_txBuffer.pop ();
if (m_txBuffer.empty ())
{
if (m_closeOnEmpty)
{
m_nscTcpSocket->disconnect ();
m_state = CLOSED;
}
break;
}
} while ((size_t) ret == size);
if (written > 0)
{
Simulator::ScheduleNow (&NscTcpSocketImpl::NotifyDataSent, this, ret);
return true;
}
return false;
}
Ptr<NscTcpSocketImpl> NscTcpSocketImpl::Copy ()
{
return CopyObject<NscTcpSocketImpl> (this);
}
void
NscTcpSocketImpl::SetSndBufSize (uint32_t size)
{
m_sndBufSize = size;
}
uint32_t
NscTcpSocketImpl::GetSndBufSize (void) const
{
return m_sndBufSize;
}
void
NscTcpSocketImpl::SetRcvBufSize (uint32_t size)
{
m_rcvBufSize = size;
}
uint32_t
NscTcpSocketImpl::GetRcvBufSize (void) const
{
return m_rcvBufSize;
}
void
NscTcpSocketImpl::SetSegSize (uint32_t size)
{
m_segmentSize = size;
}
uint32_t
NscTcpSocketImpl::GetSegSize (void) const
{
return m_segmentSize;
}
void
NscTcpSocketImpl::SetAdvWin (uint32_t window)
{
m_advertisedWindowSize = window;
}
uint32_t
NscTcpSocketImpl::GetAdvWin (void) const
{
return m_advertisedWindowSize;
}
void
NscTcpSocketImpl::SetInitialSSThresh (uint32_t threshold)
{
m_initialSsThresh = threshold;
}
uint32_t
NscTcpSocketImpl::GetInitialSSThresh (void) const
{
return m_initialSsThresh;
}
void
NscTcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
{
m_initialCWnd = cwnd;
}
uint32_t
NscTcpSocketImpl::GetInitialCwnd (void) const
{
return m_initialCWnd;
}
void
NscTcpSocketImpl::SetConnTimeout (Time timeout)
{
m_cnTimeout = timeout;
}
Time
NscTcpSocketImpl::GetConnTimeout (void) const
{
return m_cnTimeout;
}
void
NscTcpSocketImpl::SetConnCount (uint32_t count)
{
m_cnCount = count;
}
uint32_t
NscTcpSocketImpl::GetConnCount (void) const
{
return m_cnCount;
}
void
NscTcpSocketImpl::SetDelAckTimeout (Time timeout)
{
m_delAckTimeout = timeout;
}
Time
NscTcpSocketImpl::GetDelAckTimeout (void) const
{
return m_delAckTimeout;
}
void
NscTcpSocketImpl::SetDelAckMaxCount (uint32_t count)
{
m_delAckMaxCount = count;
}
uint32_t
NscTcpSocketImpl::GetDelAckMaxCount (void) const
{
return m_delAckMaxCount;
}
void
NscTcpSocketImpl::SetTcpNoDelay (bool noDelay)
{
m_noDelay = noDelay;
}
bool
NscTcpSocketImpl::GetTcpNoDelay (void) const
{
return m_noDelay;
}
void
NscTcpSocketImpl::SetPersistTimeout (Time timeout)
{
m_persistTimeout = timeout;
}
Time
NscTcpSocketImpl::GetPersistTimeout (void) const
{
return m_persistTimeout;
}
enum Socket::SocketErrno
NscTcpSocketImpl::GetNativeNs3Errno (int error) const
{
enum nsc_errno err;
if (error >= 0)
{
return ERROR_NOTERROR;
}
err = (enum nsc_errno) error;
switch (err)
{
case NSC_EADDRINUSE: // fallthrough
case NSC_EADDRNOTAVAIL: return ERROR_AFNOSUPPORT;
case NSC_EINPROGRESS: // Altough nsc sockets are nonblocking, we pretend they're not.
case NSC_EAGAIN: return ERROR_AGAIN;
case NSC_EISCONN: // fallthrough
case NSC_EALREADY: return ERROR_ISCONN;
case NSC_ECONNREFUSED: return ERROR_NOROUTETOHOST; /// \todo better mapping?
case NSC_ECONNRESET: // for no, all of these fall through
case NSC_EHOSTDOWN:
case NSC_ENETUNREACH:
case NSC_EHOSTUNREACH: return ERROR_NOROUTETOHOST;
case NSC_EMSGSIZE: return ERROR_MSGSIZE;
case NSC_ENOTCONN: return ERROR_NOTCONN;
case NSC_ESHUTDOWN: return ERROR_SHUTDOWN;
case NSC_ETIMEDOUT: return ERROR_NOTCONN; /// \todo this mapping isn't correct
case NSC_ENOTDIR: // used by eg. sysctl(2). Shouldn't happen normally,
// but is triggered by e.g. show_config().
case NSC_EUNKNOWN: return ERROR_INVAL; // Catches stacks that 'return -1' without real mapping
}
NS_ASSERT_MSG (0, "Unknown NSC error");
return ERROR_INVAL;
}
bool
NscTcpSocketImpl::SetAllowBroadcast (bool allowBroadcast)
{
if (allowBroadcast)
{
return false;
}
return true;
}
bool
NscTcpSocketImpl::GetAllowBroadcast () const
{
return false;
}
} // namespace ns3