src/internet-stack/nsc-tcp-socket-impl.cc
author Florian Westphal <fw@strlen.de>
Wed Jul 15 18:46:14 2009 +0200 (2009-07-15)
changeset 4685 ae536d9e0d6d
parent 4523 b8bdc36a3355
permissions -rw-r--r--
nsc: move nsc glue code from nsc-tcp-l4-protocol to node/nsc-glue.cc.

known problems:
- sim_interface.h is duplicated
- nsc-glue.cc adds hooks in node.cc, "hijacks" incoming packets
- nsc-glue exports NSCs INetStack (instead of wrapping it completely)
- nsc-tcp-l4-protocol and nsc-tcp-socket-impl make calls into nsc-glue
- nsc-tcp-socket-impl should really be "nsc-socket-core" (or something
like that)

needs fixing on nsc side:
- no support for multiple interfaces yet (also not yet supported
on nsc side)
- nsc initialisation still tied to IP (Adding an Interface and assigning the
IP address is a single step; it should be separate)

maybe there is more.

There is a NSC_NEXT define in nsc-glue.h, its main purpose is to flag
the places where the NSC API needs to be adapted to support multiple
interfaces in nsc.
fw@3578
     1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
fw@3578
     2
/*
fw@3578
     3
 * This program is free software; you can redistribute it and/or modify
fw@3578
     4
 * it under the terms of the GNU General Public License version 2 as
fw@3578
     5
 * published by the Free Software Foundation;
fw@3578
     6
 *
fw@3578
     7
 * This program is distributed in the hope that it will be useful,
fw@3578
     8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
fw@3578
     9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
fw@3578
    10
 * GNU General Public License for more details.
fw@3578
    11
 *
fw@3578
    12
 * You should have received a copy of the GNU General Public License
fw@3578
    13
 * along with this program; if not, write to the Free Software
fw@3578
    14
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
fw@3578
    15
 *
fw@3578
    16
 * based on tcp-socket-impl.cc, Author: Raj Bhattacharjea <raj.b@gatech.edu>
fw@3578
    17
 * Author: Florian Westphal <fw@strlen.de>
fw@3578
    18
 */
fw@3578
    19
fw@3578
    20
#include "ns3/node.h"
fw@3578
    21
#include "ns3/inet-socket-address.h"
fw@3578
    22
#include "ns3/log.h"
fw@3578
    23
#include "ns3/ipv4.h"
fw@3578
    24
#include "ipv4-end-point.h"
fw@3578
    25
#include "nsc-tcp-l4-protocol.h"
fw@3578
    26
#include "nsc-tcp-socket-impl.h"
fw@3578
    27
#include "ns3/simulation-singleton.h"
fw@3578
    28
#include "tcp-typedefs.h"
fw@3578
    29
#include "ns3/simulator.h"
fw@3578
    30
#include "ns3/packet.h"
fw@3578
    31
#include "ns3/uinteger.h"
fw@3578
    32
#include "ns3/trace-source-accessor.h"
fw@3578
    33
fw@3578
    34
#include <algorithm>
fw@3578
    35
fw@3711
    36
// for ntohs().
fw@3711
    37
#include <arpa/inet.h>
fw@3578
    38
#include <netinet/in.h>
fw@3578
    39
mathieu@3635
    40
#include "sim_interface.h"
mathieu@3635
    41
#include "sim_errno.h"
fw@3578
    42
fw@3578
    43
NS_LOG_COMPONENT_DEFINE ("NscTcpSocketImpl");
fw@3578
    44
fw@3578
    45
using namespace std;
fw@3578
    46
fw@3578
    47
namespace ns3 {
fw@3578
    48
fw@3578
    49
NS_OBJECT_ENSURE_REGISTERED (NscTcpSocketImpl);
fw@3578
    50
fw@3578
    51
TypeId
fw@3578
    52
NscTcpSocketImpl::GetTypeId ()
fw@3578
    53
{
fw@3578
    54
  static TypeId tid = TypeId("ns3::NscTcpSocketImpl")
fw@3578
    55
    .SetParent<TcpSocket> ()
fw@3578
    56
    .AddTraceSource ("CongestionWindow",
fw@3578
    57
                     "The TCP connection's congestion window",
fw@3578
    58
                     MakeTraceSourceAccessor (&NscTcpSocketImpl::m_cWnd))
fw@3578
    59
    ;
fw@3578
    60
  return tid;
fw@3578
    61
}
fw@3578
    62
fw@3578
    63
  NscTcpSocketImpl::NscTcpSocketImpl ()
fw@3578
    64
  : m_endPoint (0),
fw@3578
    65
    m_node (0),
fw@3578
    66
    m_tcp (0),
craigdo@3778
    67
    m_localAddress (Ipv4Address::GetZero ()),
craigdo@3778
    68
    m_localPort (0),
fw@3578
    69
    m_peerAddress ("0.0.0.0", 0),
fw@3578
    70
    m_errno (ERROR_NOTERROR),
fw@3578
    71
    m_shutdownSend (false),
fw@3578
    72
    m_shutdownRecv (false),
fw@3578
    73
    m_connected (false),
fw@3578
    74
    m_state (CLOSED),
fw@3578
    75
    m_closeOnEmpty (false),
fw@3578
    76
    m_txBufferSize (0),
fw@3578
    77
    m_rtt (0),
fw@3578
    78
    m_lastMeasuredRtt (Seconds(0.0))
fw@3578
    79
{
fw@3578
    80
  NS_LOG_FUNCTION (this);
fw@3578
    81
}
fw@3578
    82
fw@3578
    83
NscTcpSocketImpl::NscTcpSocketImpl(const NscTcpSocketImpl& sock)
fw@3578
    84
  : TcpSocket(sock), //copy the base class callbacks
fw@3578
    85
    m_delAckMaxCount (sock.m_delAckMaxCount),
fw@3578
    86
    m_delAckTimeout (sock.m_delAckTimeout),
fw@3578
    87
    m_endPoint (0),
fw@3578
    88
    m_node (sock.m_node),
fw@3578
    89
    m_tcp (sock.m_tcp),
fw@3578
    90
    m_remoteAddress (sock.m_remoteAddress),
fw@3578
    91
    m_remotePort (sock.m_remotePort),
fw@3578
    92
    m_localAddress (sock.m_localAddress),
fw@3578
    93
    m_localPort (sock.m_localPort),
fw@3578
    94
    m_peerAddress (sock.m_peerAddress),
fw@3578
    95
    m_errno (sock.m_errno),
fw@3578
    96
    m_shutdownSend (sock.m_shutdownSend),
fw@3578
    97
    m_shutdownRecv (sock.m_shutdownRecv),
fw@3578
    98
    m_connected (sock.m_connected),
fw@3578
    99
    m_state (sock.m_state),
fw@3578
   100
    m_closeOnEmpty (sock.m_closeOnEmpty),
fw@3578
   101
    m_segmentSize (sock.m_segmentSize),
fw@3578
   102
    m_rxWindowSize (sock.m_rxWindowSize),
fw@3578
   103
    m_advertisedWindowSize (sock.m_advertisedWindowSize),
fw@3578
   104
    m_cWnd (sock.m_cWnd),
fw@3578
   105
    m_ssThresh (sock.m_ssThresh),
fw@3578
   106
    m_initialCWnd (sock.m_initialCWnd),
fw@3578
   107
    m_rtt (0),
fw@3578
   108
    m_lastMeasuredRtt (Seconds(0.0)),
fw@3578
   109
    m_cnTimeout (sock.m_cnTimeout),
fw@3578
   110
    m_cnCount (sock.m_cnCount),
fw@3578
   111
    m_rxAvailable (0),
fw@3578
   112
    m_nscTcpSocket (0),
fw@3578
   113
    m_sndBufSize (sock.m_sndBufSize)
fw@3578
   114
{
fw@3578
   115
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   116
  NS_LOG_LOGIC("Invoked the copy constructor");
fw@3578
   117
  //copy the pending data if necessary
fw@3578
   118
  if(!sock.m_txBuffer.empty () )
fw@3578
   119
    {
fw@3578
   120
      m_txBuffer = sock.m_txBuffer;
fw@3578
   121
    }
fw@3578
   122
  //copy the rtt if necessary
fw@3578
   123
  if (sock.m_rtt)
fw@3578
   124
    {
fw@3578
   125
      m_rtt = sock.m_rtt->Copy();
fw@3578
   126
    }
fw@3578
   127
  //can't "copy" the endpoint just yes, must do this when we know the peer info
fw@3578
   128
  //too; this is in SYN_ACK_TX
fw@3578
   129
}
fw@3578
   130
fw@3578
   131
NscTcpSocketImpl::~NscTcpSocketImpl ()
fw@3578
   132
{
fw@3578
   133
  NS_LOG_FUNCTION(this);
fw@3578
   134
  m_node = 0;
fw@3578
   135
  if (m_endPoint != 0)
fw@3578
   136
    {
fw@3578
   137
      NS_ASSERT (m_tcp != 0);
fw@3578
   138
      /**
fw@3578
   139
       * Note that this piece of code is a bit tricky:
fw@3578
   140
       * when DeAllocate is called, it will call into
fw@3578
   141
       * Ipv4EndPointDemux::Deallocate which triggers
fw@3578
   142
       * a delete of the associated endPoint which triggers
fw@3578
   143
       * in turn a call to the method ::Destroy below
fw@3578
   144
       * will will zero the m_endPoint field.
fw@3578
   145
       */
fw@3578
   146
      NS_ASSERT (m_endPoint != 0);
fw@3578
   147
      m_tcp->DeAllocate (m_endPoint);
fw@3578
   148
      NS_ASSERT (m_endPoint == 0);
fw@3578
   149
    }
fw@3578
   150
  m_tcp = 0;
fw@3578
   151
}
fw@3578
   152
fw@3578
   153
void
fw@3578
   154
NscTcpSocketImpl::SetNode (Ptr<Node> node)
fw@3578
   155
{
fw@3578
   156
  m_node = node;
fw@3578
   157
  // Initialize some variables 
fw@3578
   158
  m_cWnd = m_initialCWnd * m_segmentSize;
fw@3578
   159
  m_rxWindowSize = m_advertisedWindowSize;
fw@3578
   160
}
fw@3578
   161
fw@3578
   162
void 
fw@3578
   163
NscTcpSocketImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
fw@3578
   164
{
fw@3578
   165
  m_tcp = tcp;
fw@4685
   166
  m_nscTcpSocket = m_node->GetNscInetStack()->new_tcp_socket();
fw@3578
   167
}
fw@4685
   168
void
fw@3578
   169
NscTcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
fw@3578
   170
{
fw@3578
   171
  m_rtt = rtt;
fw@3578
   172
}
fw@3578
   173
fw@3578
   174
fw@3578
   175
enum Socket::SocketErrno
fw@3578
   176
NscTcpSocketImpl::GetErrno (void) const
fw@3578
   177
{
fw@3578
   178
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   179
  return m_errno;
fw@3578
   180
}
fw@3578
   181
fw@3578
   182
Ptr<Node>
fw@3578
   183
NscTcpSocketImpl::GetNode (void) const
fw@3578
   184
{
fw@3578
   185
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   186
  return m_node;
fw@3578
   187
}
fw@3578
   188
fw@3578
   189
void 
fw@3578
   190
NscTcpSocketImpl::Destroy (void)
fw@3578
   191
{
fw@3578
   192
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   193
  m_node = 0;
fw@3578
   194
  m_endPoint = 0;
fw@3578
   195
  m_tcp = 0;
fw@3578
   196
}
fw@3578
   197
int
fw@3578
   198
NscTcpSocketImpl::FinishBind (void)
fw@3578
   199
{
fw@3578
   200
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   201
  if (m_endPoint == 0)
fw@3578
   202
    {
fw@3578
   203
      return -1;
fw@3578
   204
    }
fw@3578
   205
  m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
fw@3578
   206
  m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
fw@3578
   207
  m_localAddress = m_endPoint->GetLocalAddress ();
fw@3578
   208
  m_localPort = m_endPoint->GetLocalPort ();
fw@3578
   209
  return 0;
fw@3578
   210
}
fw@3578
   211
fw@3578
   212
int
fw@3578
   213
NscTcpSocketImpl::Bind (void)
fw@3578
   214
{
fw@3578
   215
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   216
  m_endPoint = m_tcp->Allocate ();
fw@3578
   217
  return FinishBind ();
fw@3578
   218
}
fw@3578
   219
int 
fw@3578
   220
NscTcpSocketImpl::Bind (const Address &address)
fw@3578
   221
{
fw@3578
   222
  NS_LOG_FUNCTION (this<<address);
fw@3578
   223
  if (!InetSocketAddress::IsMatchingType (address))
fw@3578
   224
    {
fw@3578
   225
      return ERROR_INVAL;
fw@3578
   226
    }
fw@3578
   227
  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
fw@3578
   228
  Ipv4Address ipv4 = transport.GetIpv4 ();
fw@3578
   229
  uint16_t port = transport.GetPort ();
fw@3578
   230
  if (ipv4 == Ipv4Address::GetAny () && port == 0)
fw@3578
   231
    {
fw@3578
   232
      m_endPoint = m_tcp->Allocate ();
fw@3578
   233
      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
fw@3578
   234
    }
fw@3578
   235
  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
fw@3578
   236
    {
fw@3578
   237
      m_endPoint = m_tcp->Allocate (port);
fw@3578
   238
      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
fw@3578
   239
    }
fw@3578
   240
  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
fw@3578
   241
    {
fw@3578
   242
      m_endPoint = m_tcp->Allocate (ipv4);
fw@3578
   243
      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
fw@3578
   244
    }
fw@3578
   245
  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
fw@3578
   246
    {
fw@3578
   247
      m_endPoint = m_tcp->Allocate (ipv4, port);
fw@3578
   248
      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
fw@3578
   249
    }
fw@3578
   250
fw@3578
   251
  m_localPort = port;
fw@3578
   252
  return FinishBind ();
fw@3578
   253
}
fw@3578
   254
fw@3578
   255
int 
fw@3578
   256
NscTcpSocketImpl::ShutdownSend (void)
fw@3578
   257
{
fw@3578
   258
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   259
  m_shutdownSend = true;
fw@3578
   260
  return 0;
fw@3578
   261
}
fw@3578
   262
int 
fw@3578
   263
NscTcpSocketImpl::ShutdownRecv (void)
fw@3578
   264
{
fw@3578
   265
  NS_LOG_FUNCTION_NOARGS ();
mathieu@4491
   266
  m_shutdownRecv = true;
fw@3578
   267
  return 0;
fw@3578
   268
}
fw@3578
   269
fw@3578
   270
int
fw@3578
   271
NscTcpSocketImpl::Close (void)
fw@3578
   272
{
fw@3578
   273
  NS_LOG_FUNCTION (this << m_state);
fw@3578
   274
fw@3578
   275
  if (m_state == CLOSED)
fw@3578
   276
    {
fw@3578
   277
      return -1;
fw@3578
   278
    }
fw@3578
   279
  if (!m_txBuffer.empty ())
fw@3578
   280
    { // App close with pending data must wait until all data transmitted
fw@3578
   281
      m_closeOnEmpty = true;
fw@3578
   282
      NS_LOG_LOGIC("Socket " << this << 
fw@3578
   283
                   " deferring close, state " << m_state);
fw@3578
   284
      return 0;
fw@3578
   285
    }
fw@3578
   286
fw@3578
   287
  m_nscTcpSocket->disconnect();
fw@3578
   288
  m_state = CLOSED;
fw@3578
   289
  ShutdownSend ();
fw@3578
   290
  return 0;
fw@3578
   291
}
fw@3578
   292
fw@3578
   293
int
fw@3578
   294
NscTcpSocketImpl::Connect (const Address & address)
fw@3578
   295
{
fw@3578
   296
  NS_LOG_FUNCTION (this << address);
fw@3578
   297
  if (m_endPoint == 0)
fw@3578
   298
    {
fw@3578
   299
      if (Bind () == -1)
fw@3578
   300
        {
fw@3578
   301
          NS_ASSERT (m_endPoint == 0);
fw@3578
   302
          return -1;
fw@3578
   303
        }
fw@3578
   304
      NS_ASSERT (m_endPoint != 0);
fw@3578
   305
    }
fw@3578
   306
  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
fw@3578
   307
  m_remoteAddress = transport.GetIpv4 ();
fw@3578
   308
  m_remotePort = transport.GetPort ();
fw@3578
   309
fw@3711
   310
  std::ostringstream ss;
fw@3711
   311
  m_remoteAddress.Print(ss);
fw@3711
   312
  std::string ipstring = ss.str ();
fw@3578
   313
fw@3711
   314
  m_nscTcpSocket->connect(ipstring.c_str (), m_remotePort);
fw@3578
   315
  m_state = SYN_SENT;
fw@3578
   316
  return 0;
fw@3578
   317
}
fw@3578
   318
fw@3578
   319
int
fw@3578
   320
NscTcpSocketImpl::Send (const Ptr<Packet> p, uint32_t flags)
fw@3578
   321
{
fw@3578
   322
  NS_LOG_FUNCTION (this << p);
fw@3578
   323
fw@3578
   324
  NS_ASSERT (p->GetSize () > 0);
fw@3578
   325
  if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
fw@3578
   326
  {
fw@3578
   327
    if (p->GetSize () > GetTxAvailable ())
fw@3578
   328
    {
fw@3578
   329
      m_errno = ERROR_MSGSIZE;
fw@3578
   330
      return -1;
fw@3578
   331
    }
fw@3578
   332
mathieu@3780
   333
    uint32_t sent = p->GetSize ();
fw@3578
   334
    if (m_state == ESTABLISHED)
fw@3578
   335
      {
mathieu@3780
   336
        m_txBuffer.push(p);
mathieu@3780
   337
        m_txBufferSize += sent;
mathieu@3780
   338
        SendPendingData();
fw@3578
   339
      }
fw@3578
   340
      else
fw@3578
   341
      {  // SYN_SET -- Queue Data
fw@3578
   342
         m_txBuffer.push(p);
mathieu@3780
   343
         m_txBufferSize += sent;
fw@3578
   344
      }
mathieu@3780
   345
    return sent;
fw@3578
   346
  }
fw@3578
   347
  else
fw@3578
   348
  {
fw@3578
   349
    m_errno = ERROR_NOTCONN;
fw@3578
   350
    return -1;
fw@3578
   351
  }
fw@3578
   352
}
fw@3578
   353
fw@3578
   354
int
fw@3578
   355
NscTcpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
fw@3578
   356
{
fw@3578
   357
  NS_LOG_FUNCTION (this << address << p);
fw@3578
   358
  if (!m_connected)
fw@3578
   359
    {
fw@3578
   360
      m_errno = ERROR_NOTCONN;
fw@3578
   361
      return -1;
fw@3578
   362
    }
fw@3578
   363
  else
fw@3578
   364
    {
fw@3578
   365
      return Send (p, flags); //drop the address according to BSD manpages
fw@3578
   366
    }
fw@3578
   367
}
fw@3578
   368
fw@3578
   369
uint32_t
fw@3578
   370
NscTcpSocketImpl::GetTxAvailable (void) const
fw@3578
   371
{
fw@3578
   372
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   373
  if (m_txBufferSize != 0)
fw@3578
   374
    {
fw@3578
   375
      NS_ASSERT (m_txBufferSize <= m_sndBufSize);
fw@3578
   376
      return m_sndBufSize - m_txBufferSize;
fw@3578
   377
    }
fw@3578
   378
  else
fw@3578
   379
    {
fw@3578
   380
      return m_sndBufSize;
fw@3578
   381
    }
fw@3578
   382
}
fw@3578
   383
fw@3578
   384
int
craigdo@3772
   385
NscTcpSocketImpl::Listen (void)
fw@3578
   386
{
craigdo@3772
   387
  NS_LOG_FUNCTION (this);
fw@3578
   388
  m_nscTcpSocket->listen(m_localPort);
fw@3578
   389
  m_state = LISTEN;
fw@3578
   390
  return 0;
fw@3578
   391
}
fw@3578
   392
fw@3578
   393
fw@3578
   394
void
fw@3578
   395
NscTcpSocketImpl::NSCWakeup ()
fw@3578
   396
{
fw@3578
   397
  switch (m_state) {
fw@3578
   398
  case SYN_SENT:
fw@3578
   399
      if (!m_nscTcpSocket->is_connected())
fw@3578
   400
          break;
fw@3578
   401
      m_state = ESTABLISHED;
fw@3578
   402
      Simulator::ScheduleNow(&NscTcpSocketImpl::ConnectionSucceeded, this);
fw@3578
   403
      // fall through to schedule read/write events
fw@3578
   404
  case ESTABLISHED:
fw@3578
   405
      if (!m_txBuffer.empty ())
fw@3578
   406
          Simulator::ScheduleNow(&NscTcpSocketImpl::SendPendingData, this);
fw@3578
   407
      Simulator::ScheduleNow(&NscTcpSocketImpl::ReadPendingData, this);
fw@3578
   408
      break;
fw@3578
   409
  case LISTEN:
fw@3578
   410
      Simulator::ScheduleNow(&NscTcpSocketImpl::Accept, this);
fw@3578
   411
      break;
fw@3578
   412
  case CLOSED: break;
fw@3578
   413
  default:
fw@3578
   414
      NS_LOG_DEBUG (this << " invalid state: " << m_state);
fw@3578
   415
  }
fw@3578
   416
}
fw@3578
   417
fw@3578
   418
Ptr<Packet>
fw@3578
   419
NscTcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
fw@3578
   420
{
fw@3578
   421
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   422
  if (m_deliveryQueue.empty() )
fw@3578
   423
    {
mathieu@3780
   424
      m_errno = ERROR_AGAIN;
fw@3578
   425
      return 0;
fw@3578
   426
    }
fw@3578
   427
  Ptr<Packet> p = m_deliveryQueue.front ();
fw@3578
   428
  if (p->GetSize () <= maxSize)
fw@3578
   429
    {
fw@3578
   430
      m_deliveryQueue.pop ();
fw@3578
   431
      m_rxAvailable -= p->GetSize ();
fw@3578
   432
    }
fw@3578
   433
  else
fw@3578
   434
    {
mathieu@3780
   435
      m_errno = ERROR_AGAIN;
fw@3578
   436
      p = 0;
fw@3578
   437
    }
fw@3578
   438
  return p;
fw@3578
   439
}
fw@3578
   440
fw@3578
   441
Ptr<Packet>
fw@3578
   442
NscTcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
fw@3578
   443
  Address &fromAddress)
fw@3578
   444
{
fw@3578
   445
  NS_LOG_FUNCTION (this << maxSize << flags);
fw@3578
   446
  Ptr<Packet> packet = Recv (maxSize, flags);
fw@3578
   447
  if (packet != 0)
fw@3578
   448
    {
fw@3578
   449
      SocketAddressTag tag;
fw@3578
   450
      bool found;
mathieu@4523
   451
      found = packet->PeekPacketTag (tag);
fw@3578
   452
      NS_ASSERT (found);
fw@3578
   453
      fromAddress = tag.GetAddress ();
fw@3578
   454
    }
fw@3578
   455
  return packet;
fw@3578
   456
}
fw@3578
   457
craigdo@3778
   458
int
craigdo@3778
   459
NscTcpSocketImpl::GetSockName (Address &address) const
craigdo@3778
   460
{
craigdo@3778
   461
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3778
   462
  address = InetSocketAddress(m_localAddress, m_localPort);
craigdo@3778
   463
  return 0;
craigdo@3778
   464
}
craigdo@3778
   465
fw@3578
   466
uint32_t
fw@3578
   467
NscTcpSocketImpl::GetRxAvailable (void) const
fw@3578
   468
{
fw@3578
   469
  NS_LOG_FUNCTION_NOARGS ();
fw@3578
   470
  // We separately maintain this state to avoid walking the queue 
fw@3578
   471
  // every time this might be called
fw@3578
   472
  return m_rxAvailable;
fw@3578
   473
}
fw@3578
   474
fw@3578
   475
void
fw@3578
   476
NscTcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
fw@3578
   477
{
fw@3578
   478
  NSCWakeup();
fw@3578
   479
}
fw@3578
   480
fw@3578
   481
void NscTcpSocketImpl::CompleteFork(void)
fw@3578
   482
{
fw@3578
   483
  // The address pairs (m_localAddress, m_localPort, m_remoteAddress, m_remotePort)
fw@3578
   484
  // are bogus, but this isn't important at the moment, because
fw@3578
   485
  // address <-> Socket handling is done by NSC internally.
fw@3578
   486
  // We only need to add the new ns-3 socket to the list of sockets, so
fw@3578
   487
  // we use plain Allocate() instead of Allocate(m_localAddress, ... )
fw@3869
   488
  struct sockaddr_in sin;
fw@3869
   489
  size_t sin_len = sizeof(sin);
fw@3578
   490
fw@3869
   491
  if (0 == m_nscTcpSocket->getpeername((struct sockaddr*) &sin, &sin_len)) {
fw@3869
   492
    m_remotePort = ntohs(sin.sin_port);
fw@3869
   493
    m_remoteAddress = m_remoteAddress.Deserialize((const uint8_t*) &sin.sin_addr);
fw@3578
   494
    m_peerAddress = InetSocketAddress(m_remoteAddress, m_remotePort);
fw@3578
   495
  }
fw@3578
   496
fw@3578
   497
  m_endPoint = m_tcp->Allocate ();
fw@3578
   498
fw@3578
   499
  //the cloned socket with be in listen state, so manually change state
fw@3578
   500
  NS_ASSERT(m_state == LISTEN);
fw@3578
   501
  m_state = ESTABLISHED;
fw@3578
   502
fw@3869
   503
  sin_len = sizeof(sin);
fw@3869
   504
fw@3869
   505
  if (0 == m_nscTcpSocket->getsockname((struct sockaddr *) &sin, &sin_len))
fw@3869
   506
    m_localAddress = m_localAddress.Deserialize((const uint8_t*) &sin.sin_addr);
fw@3578
   507
fw@3578
   508
  NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " accepted connection from " 
fw@3578
   509
                 << m_remoteAddress << ":" << m_remotePort
fw@3578
   510
                 << " to " << m_localAddress << ":" << m_localPort);
fw@3578
   511
  //equivalent to FinishBind
fw@3578
   512
  m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
fw@3578
   513
  m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
fw@3578
   514
fw@3578
   515
  NotifyNewConnectionCreated (this, m_peerAddress);
fw@3578
   516
}
fw@3578
   517
fw@3578
   518
void NscTcpSocketImpl::ConnectionSucceeded()
fw@3578
   519
{ // We would preferred to have scheduled an event directly to
fw@3578
   520
  // NotifyConnectionSucceeded, but (sigh) these are protected
fw@3578
   521
  // and we can get the address of it :(
fw@3869
   522
  struct sockaddr_in sin;
fw@3869
   523
  size_t sin_len = sizeof(sin);
fw@3869
   524
  if (0 == m_nscTcpSocket->getsockname((struct sockaddr *) &sin, &sin_len)) {
fw@3869
   525
    m_localAddress = m_localAddress.Deserialize((const uint8_t*)&sin.sin_addr);
fw@3869
   526
    m_localPort = ntohs(sin.sin_port);
fw@3578
   527
  }
fw@3578
   528
fw@3578
   529
  NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " connected to "
fw@3578
   530
                 << m_remoteAddress << ":" << m_remotePort
fw@3578
   531
                 << " from " << m_localAddress << ":" << m_localPort);
fw@3578
   532
  NotifyConnectionSucceeded();
fw@3578
   533
}
fw@3578
   534
fw@3578
   535
fw@3578
   536
bool NscTcpSocketImpl::Accept (void)
fw@3578
   537
{
fw@3578
   538
  if (m_state == CLOSED)
fw@3578
   539
    {  // Happens if application closes listening socket after Accept() was scheduled.
fw@3578
   540
      return false;
fw@3578
   541
    }
fw@3578
   542
  NS_ASSERT (m_state == LISTEN);
fw@3578
   543
fw@3578
   544
  if (!m_nscTcpSocket->is_listening())
fw@3578
   545
    {
fw@3578
   546
      return false;
fw@3578
   547
    }
fw@3578
   548
  INetStreamSocket *newsock;
fw@3578
   549
  int res = m_nscTcpSocket->accept(&newsock);
fw@3578
   550
  if (res != 0)
fw@3578
   551
    {
fw@3578
   552
      return false;
fw@3578
   553
    }
fw@3578
   554
// We could obtain a fromAddress using getpeername, but we've already
fw@3578
   555
// finished the tcp handshake here, i.e. this is a new connection
fw@3578
   556
// and not a connection request.
fw@3578
   557
// if (!NotifyConnectionRequest(fromAddress))
fw@3578
   558
//   return true;
fw@3578
   559
fw@3578
   560
  // Clone the socket
fw@3578
   561
  Ptr<NscTcpSocketImpl> newSock = Copy ();
fw@3578
   562
  newSock->m_nscTcpSocket = newsock;
fw@3578
   563
  NS_LOG_LOGIC ("Cloned a NscTcpSocketImpl " << newSock);
fw@3578
   564
fw@3578
   565
  Simulator::ScheduleNow (&NscTcpSocketImpl::CompleteFork, newSock);
fw@3578
   566
  return true;
fw@3578
   567
}
fw@3578
   568
fw@3578
   569
bool NscTcpSocketImpl::ReadPendingData (void)
fw@3578
   570
{
fw@3578
   571
  if (m_state != ESTABLISHED)
fw@3578
   572
    {
fw@3578
   573
      return false;
fw@3578
   574
    }
fw@3578
   575
  int len, err;
fw@3578
   576
  uint8_t buffer[8192];
fw@3578
   577
  len = sizeof(buffer);
fw@3578
   578
  m_errno = ERROR_NOTERROR;
fw@3578
   579
  err = m_nscTcpSocket->read_data(buffer, &len);
fw@3578
   580
  if (err == 0 && len == 0)
fw@3578
   581
    {
fw@3578
   582
      NS_LOG_LOGIC ("ReadPendingData got EOF from socket");
fw@3578
   583
      m_state = CLOSED;
fw@3578
   584
      return false;
fw@3578
   585
    }
fw@3578
   586
  m_errno = GetNativeNs3Errno(err);
fw@3578
   587
  switch (m_errno)
fw@3578
   588
    {
fw@3578
   589
      case ERROR_NOTERROR: break; // some data was sent
fw@3578
   590
      case ERROR_AGAIN: return false;
fw@3578
   591
      default:
fw@3578
   592
        NS_LOG_WARN ("Error (" << err << ") " <<
fw@3578
   593
                     "during read_data, ns-3 errno set to" << m_errno);
fw@3578
   594
        m_state = CLOSED;
fw@3578
   595
        return false;
fw@3578
   596
    }
fw@3578
   597
fw@3578
   598
  Ptr<Packet> p =  Create<Packet> (buffer, len);
fw@3578
   599
fw@3578
   600
  SocketAddressTag tag;
fw@3578
   601
fw@3578
   602
  tag.SetAddress (m_peerAddress);
mathieu@4523
   603
  p->AddPacketTag (tag);
fw@3578
   604
  m_deliveryQueue.push (p);
fw@3578
   605
  m_rxAvailable += p->GetSize ();
fw@3578
   606
fw@3578
   607
  NotifyDataRecv ();
fw@3578
   608
  return true;
fw@3578
   609
}
fw@3578
   610
fw@3578
   611
bool NscTcpSocketImpl::SendPendingData (void)
fw@3578
   612
{
fw@3578
   613
  NS_LOG_FUNCTION (this);
fw@3578
   614
  NS_LOG_LOGIC ("ENTERING SendPendingData");
fw@3578
   615
fw@3578
   616
  if (m_txBuffer.empty ())
fw@3578
   617
    {
fw@3578
   618
      return false;
fw@3578
   619
    }
fw@3578
   620
fw@3578
   621
  int ret;
fw@3578
   622
  size_t size, written = 0;
fw@3578
   623
fw@3578
   624
  do {
mathieu@3780
   625
    NS_ASSERT (!m_txBuffer.empty ());
fw@3578
   626
    Ptr<Packet> &p = m_txBuffer.front ();
fw@3578
   627
    size = p->GetSize ();
fw@3578
   628
    NS_ASSERT (size > 0);
fw@3578
   629
fw@3578
   630
    m_errno = ERROR_NOTERROR;
fw@3578
   631
    ret = m_nscTcpSocket->send_data((const char *)p->PeekData (), size);
fw@3578
   632
    if (ret <= 0)
fw@3578
   633
      {
fw@3578
   634
        break;
fw@3578
   635
      }
fw@3578
   636
    written += ret;
fw@3578
   637
fw@3578
   638
    NS_ASSERT (m_txBufferSize >= (size_t)ret);
fw@3578
   639
    m_txBufferSize -= ret;
fw@3578
   640
fw@3578
   641
    if ((size_t)ret < size)
fw@3578
   642
      {
fw@3578
   643
        p->RemoveAtStart(ret);
fw@3578
   644
        break;
fw@3578
   645
      }
fw@3578
   646
fw@3578
   647
    m_txBuffer.pop ();
fw@3578
   648
fw@3578
   649
    if (m_txBuffer.empty ())
fw@3578
   650
      {
fw@3578
   651
        if (m_closeOnEmpty)
fw@3578
   652
          {
fw@3578
   653
            m_nscTcpSocket->disconnect();
fw@3578
   654
            m_state = CLOSED;
fw@3578
   655
          }
fw@3578
   656
        break;
fw@3578
   657
      }
fw@3578
   658
  } while ((size_t) ret == size);
fw@3578
   659
fw@3578
   660
  if (written > 0)
fw@3578
   661
    {
fw@3578
   662
      Simulator::ScheduleNow(&NscTcpSocketImpl::NotifyDataSent, this, ret);
fw@3578
   663
      return true;
fw@3578
   664
    }
fw@3578
   665
  return false;
fw@3578
   666
}
fw@3578
   667
fw@3578
   668
Ptr<NscTcpSocketImpl> NscTcpSocketImpl::Copy ()
fw@3578
   669
{
fw@3578
   670
  return CopyObject<NscTcpSocketImpl> (this);
fw@3578
   671
}
fw@3578
   672
fw@3578
   673
void
fw@3578
   674
NscTcpSocketImpl::SetSndBufSize (uint32_t size)
fw@3578
   675
{
fw@3578
   676
  m_sndBufSize = size;
fw@3578
   677
}
fw@3578
   678
fw@3578
   679
uint32_t
fw@3578
   680
NscTcpSocketImpl::GetSndBufSize (void) const
fw@3578
   681
{
fw@3578
   682
  return m_sndBufSize;
fw@3578
   683
}
fw@3578
   684
fw@3578
   685
void
fw@3578
   686
NscTcpSocketImpl::SetRcvBufSize (uint32_t size)
fw@3578
   687
{
fw@3578
   688
  m_rcvBufSize = size;
fw@3578
   689
}
fw@3578
   690
fw@3578
   691
uint32_t
fw@3578
   692
NscTcpSocketImpl::GetRcvBufSize (void) const
fw@3578
   693
{
fw@3578
   694
  return m_rcvBufSize;
fw@3578
   695
}
fw@3578
   696
fw@3578
   697
void
fw@3578
   698
NscTcpSocketImpl::SetSegSize (uint32_t size)
fw@3578
   699
{
fw@3578
   700
  m_segmentSize = size;
fw@3578
   701
}
fw@3578
   702
fw@3578
   703
uint32_t
fw@3578
   704
NscTcpSocketImpl::GetSegSize (void) const
fw@3578
   705
{
fw@3578
   706
  return m_segmentSize;
fw@3578
   707
}
fw@3578
   708
fw@3578
   709
void
fw@3578
   710
NscTcpSocketImpl::SetAdvWin (uint32_t window)
fw@3578
   711
{
fw@3578
   712
  m_advertisedWindowSize = window;
fw@3578
   713
}
fw@3578
   714
fw@3578
   715
uint32_t
fw@3578
   716
NscTcpSocketImpl::GetAdvWin (void) const
fw@3578
   717
{
fw@3578
   718
  return m_advertisedWindowSize;
fw@3578
   719
}
fw@3578
   720
fw@3578
   721
void
fw@3578
   722
NscTcpSocketImpl::SetSSThresh (uint32_t threshold)
fw@3578
   723
{
fw@3578
   724
  m_ssThresh = threshold;
fw@3578
   725
}
fw@3578
   726
fw@3578
   727
uint32_t
fw@3578
   728
NscTcpSocketImpl::GetSSThresh (void) const
fw@3578
   729
{
fw@3578
   730
  return m_ssThresh;
fw@3578
   731
}
fw@3578
   732
fw@3578
   733
void
fw@3578
   734
NscTcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
fw@3578
   735
{
fw@3578
   736
  m_initialCWnd = cwnd;
fw@3578
   737
}
fw@3578
   738
fw@3578
   739
uint32_t
fw@3578
   740
NscTcpSocketImpl::GetInitialCwnd (void) const
fw@3578
   741
{
fw@3578
   742
  return m_initialCWnd;
fw@3578
   743
}
fw@3578
   744
fw@3578
   745
void 
fw@3578
   746
NscTcpSocketImpl::SetConnTimeout (Time timeout)
fw@3578
   747
{
fw@3578
   748
  m_cnTimeout = timeout;
fw@3578
   749
}
fw@3578
   750
fw@3578
   751
Time
fw@3578
   752
NscTcpSocketImpl::GetConnTimeout (void) const
fw@3578
   753
{
fw@3578
   754
  return m_cnTimeout;
fw@3578
   755
}
fw@3578
   756
fw@3578
   757
void 
fw@3578
   758
NscTcpSocketImpl::SetConnCount (uint32_t count)
fw@3578
   759
{
fw@3578
   760
  m_cnCount = count;
fw@3578
   761
}
fw@3578
   762
fw@3578
   763
uint32_t 
fw@3578
   764
NscTcpSocketImpl::GetConnCount (void) const
fw@3578
   765
{
fw@3578
   766
  return m_cnCount;
fw@3578
   767
}
fw@3578
   768
fw@3578
   769
void 
fw@3578
   770
NscTcpSocketImpl::SetDelAckTimeout (Time timeout)
fw@3578
   771
{
fw@3578
   772
  m_delAckTimeout = timeout;
fw@3578
   773
}
fw@3578
   774
fw@3578
   775
Time
fw@3578
   776
NscTcpSocketImpl::GetDelAckTimeout (void) const
fw@3578
   777
{
fw@3578
   778
  return m_delAckTimeout;
fw@3578
   779
}
fw@3578
   780
fw@3578
   781
void
fw@3578
   782
NscTcpSocketImpl::SetDelAckMaxCount (uint32_t count)
fw@3578
   783
{
fw@3578
   784
  m_delAckMaxCount = count;
fw@3578
   785
}
fw@3578
   786
fw@3578
   787
uint32_t
fw@3578
   788
NscTcpSocketImpl::GetDelAckMaxCount (void) const
fw@3578
   789
{
fw@3578
   790
  return m_delAckMaxCount;
fw@3578
   791
}
fw@3578
   792
fw@3578
   793
enum Socket::SocketErrno
fw@3578
   794
NscTcpSocketImpl::GetNativeNs3Errno(int error) const
fw@3578
   795
{
fw@3578
   796
  enum nsc_errno err;
fw@3578
   797
fw@3578
   798
  if (error >= 0)
fw@3578
   799
    {
fw@3578
   800
       return ERROR_NOTERROR;
fw@3578
   801
    }
fw@3578
   802
  err = (enum nsc_errno) error;
fw@3578
   803
  switch (err)
fw@3578
   804
    {
fw@3578
   805
      case NSC_EADDRINUSE: // fallthrough
fw@3578
   806
      case NSC_EADDRNOTAVAIL: return ERROR_AFNOSUPPORT;
fw@3578
   807
      case NSC_EINPROGRESS: // Altough nsc sockets are nonblocking, we pretend they're not.
fw@3578
   808
      case NSC_EAGAIN: return ERROR_AGAIN;
fw@3578
   809
      case NSC_EISCONN: // fallthrough
fw@3578
   810
      case NSC_EALREADY: return ERROR_ISCONN;
fw@3578
   811
      case NSC_ECONNREFUSED: return ERROR_NOROUTETOHOST; // XXX, better mapping?
fw@3578
   812
      case NSC_ECONNRESET: // for no, all of these fall through
fw@3578
   813
      case NSC_EHOSTDOWN:
fw@3578
   814
      case NSC_ENETUNREACH:
fw@3578
   815
      case NSC_EHOSTUNREACH: return ERROR_NOROUTETOHOST;
fw@3578
   816
      case NSC_EMSGSIZE: return ERROR_MSGSIZE;
fw@3578
   817
      case NSC_ENOTCONN: return ERROR_NOTCONN;
fw@3578
   818
      case NSC_ESHUTDOWN: return ERROR_SHUTDOWN;
fw@3578
   819
      case NSC_ETIMEDOUT: return ERROR_NOTCONN; // XXX - this mapping isn't correct
fw@3578
   820
      case NSC_ENOTDIR: // used by eg. sysctl(2). Shouldn't happen normally,
fw@3578
   821
                        // but is triggered by e.g. show_config().
fw@3578
   822
      case NSC_EUNKNOWN: return ERROR_INVAL; // Catches stacks that 'return -1' without real mapping
fw@3578
   823
    }
fw@3578
   824
  NS_ASSERT_MSG(0, "Unknown NSC error");
fw@3578
   825
  return ERROR_INVAL;
fw@3578
   826
}
fw@3578
   827
fw@3578
   828
}//namespace ns3