A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
udp-socket-impl.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2007 INRIA
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation;
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
*
18
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
*/
20
21
#include "ns3/log.h"
22
#include "ns3/node.h"
23
#include "ns3/inet-socket-address.h"
24
#include "ns3/inet6-socket-address.h"
25
#include "ns3/ipv4-route.h"
26
#include "ns3/ipv6-route.h"
27
#include "ns3/ipv4.h"
28
#include "ns3/ipv6.h"
29
#include "ns3/ipv4-header.h"
30
#include "ns3/ipv4-routing-protocol.h"
31
#include "ns3/ipv6-routing-protocol.h"
32
#include "ns3/udp-socket-factory.h"
33
#include "ns3/trace-source-accessor.h"
34
#include "ns3/ipv4-packet-info-tag.h"
35
#include "
udp-socket-impl.h
"
36
#include "
udp-l4-protocol.h
"
37
#include "
ipv4-end-point.h
"
38
#include "
ipv6-end-point.h
"
39
#include <limits>
40
41
NS_LOG_COMPONENT_DEFINE
(
"UdpSocketImpl"
);
42
43
namespace
ns3 {
44
45
NS_OBJECT_ENSURE_REGISTERED
(UdpSocketImpl);
46
47
static
const
uint32_t
MAX_IPV4_UDP_DATAGRAM_SIZE
= 65507;
48
49
// Add attributes generic to all UdpSockets to base class UdpSocket
50
TypeId
51
UdpSocketImpl::GetTypeId
(
void
)
52
{
53
static
TypeId
tid =
TypeId
(
"ns3::UdpSocketImpl"
)
54
.
SetParent
<
UdpSocket
> ()
55
.AddConstructor<UdpSocketImpl> ()
56
.AddTraceSource (
"Drop"
,
"Drop UDP packet due to receive buffer overflow"
,
57
MakeTraceSourceAccessor
(&
UdpSocketImpl::m_dropTrace
))
58
.AddAttribute (
"IcmpCallback"
,
"Callback invoked whenever an icmp error is received on this socket."
,
59
CallbackValue
(),
60
MakeCallbackAccessor (&
UdpSocketImpl::m_icmpCallback
),
61
MakeCallbackChecker ())
62
.AddAttribute (
"IcmpCallback6"
,
"Callback invoked whenever an icmpv6 error is received on this socket."
,
63
CallbackValue
(),
64
MakeCallbackAccessor (&
UdpSocketImpl::m_icmpCallback6
),
65
MakeCallbackChecker ())
66
;
67
return
tid;
68
}
69
70
UdpSocketImpl::UdpSocketImpl
()
71
: m_endPoint (0),
72
m_endPoint6 (0),
73
m_node (0),
74
m_udp (0),
75
m_errno (ERROR_NOTERROR),
76
m_shutdownSend (false),
77
m_shutdownRecv (false),
78
m_connected (false),
79
m_rxAvailable (0)
80
{
81
NS_LOG_FUNCTION_NOARGS
();
82
m_allowBroadcast
=
false
;
83
}
84
85
UdpSocketImpl::~UdpSocketImpl
()
86
{
87
NS_LOG_FUNCTION_NOARGS
();
88
89
// XXX todo: leave any multicast groups that have been joined
90
m_node
= 0;
96
if
(
m_endPoint
!= 0)
97
{
98
NS_ASSERT
(
m_udp
!= 0);
107
NS_ASSERT
(
m_endPoint
!= 0);
108
m_udp
->
DeAllocate
(
m_endPoint
);
109
NS_ASSERT
(
m_endPoint
== 0);
110
}
111
if
(
m_endPoint6
!= 0)
112
{
113
NS_ASSERT
(
m_udp
!= 0);
122
NS_ASSERT
(
m_endPoint6
!= 0);
123
m_udp
->
DeAllocate
(
m_endPoint6
);
124
NS_ASSERT
(
m_endPoint6
== 0);
125
}
126
m_udp
= 0;
127
}
128
129
void
130
UdpSocketImpl::SetNode
(
Ptr<Node>
node)
131
{
132
NS_LOG_FUNCTION_NOARGS
();
133
m_node
= node;
134
135
}
136
void
137
UdpSocketImpl::SetUdp
(
Ptr<UdpL4Protocol>
udp)
138
{
139
NS_LOG_FUNCTION_NOARGS
();
140
m_udp
= udp;
141
}
142
143
144
enum
Socket::SocketErrno
145
UdpSocketImpl::GetErrno
(
void
)
const
146
{
147
NS_LOG_FUNCTION_NOARGS
();
148
return
m_errno
;
149
}
150
151
enum
Socket::SocketType
152
UdpSocketImpl::GetSocketType
(
void
)
const
153
{
154
return
NS3_SOCK_DGRAM
;
155
}
156
157
Ptr<Node>
158
UdpSocketImpl::GetNode
(
void
)
const
159
{
160
NS_LOG_FUNCTION_NOARGS
();
161
return
m_node
;
162
}
163
164
void
165
UdpSocketImpl::Destroy
(
void
)
166
{
167
NS_LOG_FUNCTION_NOARGS
();
168
m_endPoint
= 0;
169
}
170
171
void
172
UdpSocketImpl::Destroy6
(
void
)
173
{
174
NS_LOG_FUNCTION_NOARGS
();
175
m_endPoint6
= 0;
176
}
177
178
int
179
UdpSocketImpl::FinishBind
(
void
)
180
{
181
NS_LOG_FUNCTION_NOARGS
();
182
bool
done =
false
;
183
if
(
m_endPoint
!= 0)
184
{
185
m_endPoint
->
SetRxCallback
(
MakeCallback
(&
UdpSocketImpl::ForwardUp
,
Ptr<UdpSocketImpl>
(
this
)));
186
m_endPoint
->
SetIcmpCallback
(
MakeCallback
(&
UdpSocketImpl::ForwardIcmp
,
Ptr<UdpSocketImpl>
(
this
)));
187
m_endPoint
->
SetDestroyCallback
(
MakeCallback
(&
UdpSocketImpl::Destroy
,
Ptr<UdpSocketImpl>
(
this
)));
188
done =
true
;
189
}
190
if
(
m_endPoint6
!= 0)
191
{
192
m_endPoint6
->
SetRxCallback
(
MakeCallback
(&
UdpSocketImpl::ForwardUp6
,
Ptr<UdpSocketImpl>
(
this
)));
193
m_endPoint6
->
SetIcmpCallback
(
MakeCallback
(&
UdpSocketImpl::ForwardIcmp6
,
Ptr<UdpSocketImpl>
(
this
)));
194
m_endPoint6
->
SetDestroyCallback
(
MakeCallback
(&
UdpSocketImpl::Destroy6
,
Ptr<UdpSocketImpl>
(
this
)));
195
done =
true
;
196
}
197
if
(done)
198
{
199
return
0;
200
}
201
return
-1;
202
}
203
204
int
205
UdpSocketImpl::Bind
(
void
)
206
{
207
NS_LOG_FUNCTION_NOARGS
();
208
m_endPoint
=
m_udp
->
Allocate
();
209
return
FinishBind
();
210
}
211
212
int
213
UdpSocketImpl::Bind6
(
void
)
214
{
215
NS_LOG_FUNCTION_NOARGS
();
216
m_endPoint6
=
m_udp
->
Allocate6
();
217
return
FinishBind
();
218
}
219
220
int
221
UdpSocketImpl::Bind
(
const
Address
&address)
222
{
223
NS_LOG_FUNCTION
(
this
<< address);
224
225
if
(
InetSocketAddress::IsMatchingType
(address))
226
{
227
InetSocketAddress
transport =
InetSocketAddress::ConvertFrom
(address);
228
Ipv4Address
ipv4 = transport.
GetIpv4
();
229
uint16_t
port
= transport.
GetPort
();
230
if
(ipv4 ==
Ipv4Address::GetAny
() && port == 0)
231
{
232
m_endPoint
=
m_udp
->
Allocate
();
233
}
234
else
if
(ipv4 ==
Ipv4Address::GetAny
() && port != 0)
235
{
236
m_endPoint
=
m_udp
->
Allocate
(port);
237
}
238
else
if
(ipv4 !=
Ipv4Address::GetAny
() && port == 0)
239
{
240
m_endPoint
=
m_udp
->
Allocate
(ipv4);
241
}
242
else
if
(ipv4 !=
Ipv4Address::GetAny
() && port != 0)
243
{
244
m_endPoint
=
m_udp
->
Allocate
(ipv4, port);
245
}
246
}
247
else
if
(
Inet6SocketAddress::IsMatchingType
(address))
248
{
249
Inet6SocketAddress
transport =
Inet6SocketAddress::ConvertFrom
(address);
250
Ipv6Address
ipv6 = transport.
GetIpv6
();
251
uint16_t
port
= transport.
GetPort
();
252
if
(ipv6 ==
Ipv6Address::GetAny
() && port == 0)
253
{
254
m_endPoint6
=
m_udp
->
Allocate6
();
255
}
256
else
if
(ipv6 ==
Ipv6Address::GetAny
() && port != 0)
257
{
258
m_endPoint6
=
m_udp
->
Allocate6
(port);
259
}
260
else
if
(ipv6 !=
Ipv6Address::GetAny
() && port == 0)
261
{
262
m_endPoint6
=
m_udp
->
Allocate6
(ipv6);
263
}
264
else
if
(ipv6 !=
Ipv6Address::GetAny
() && port != 0)
265
{
266
m_endPoint6
=
m_udp
->
Allocate6
(ipv6, port);
267
}
268
}
269
else
270
{
271
NS_LOG_ERROR
(
"Not IsMatchingType"
);
272
m_errno
=
ERROR_INVAL
;
273
return
-1;
274
}
275
276
return
FinishBind
();
277
}
278
279
int
280
UdpSocketImpl::ShutdownSend
(
void
)
281
{
282
NS_LOG_FUNCTION_NOARGS
();
283
m_shutdownSend
=
true
;
284
return
0;
285
}
286
287
int
288
UdpSocketImpl::ShutdownRecv
(
void
)
289
{
290
NS_LOG_FUNCTION_NOARGS
();
291
m_shutdownRecv
=
true
;
292
return
0;
293
}
294
295
int
296
UdpSocketImpl::Close
(
void
)
297
{
298
NS_LOG_FUNCTION_NOARGS
();
299
if
(
m_shutdownRecv
==
true
&&
m_shutdownSend
==
true
)
300
{
301
m_errno
=
Socket::ERROR_BADF
;
302
return
-1;
303
}
304
m_shutdownRecv
=
true
;
305
m_shutdownSend
=
true
;
306
return
0;
307
}
308
309
int
310
UdpSocketImpl::Connect
(
const
Address
& address)
311
{
312
NS_LOG_FUNCTION
(
this
<< address);
313
if
(
InetSocketAddress::IsMatchingType
(address) ==
true
)
314
{
315
InetSocketAddress
transport =
InetSocketAddress::ConvertFrom
(address);
316
m_defaultAddress
=
Address
(transport.
GetIpv4
());
317
m_defaultPort
= transport.
GetPort
();
318
m_connected
=
true
;
319
NotifyConnectionSucceeded
();
320
}
321
else
if
(
Inet6SocketAddress::IsMatchingType
(address) ==
true
)
322
{
323
Inet6SocketAddress
transport =
Inet6SocketAddress::ConvertFrom
(address);
324
m_defaultAddress
=
Address
(transport.
GetIpv6
());
325
m_defaultPort
= transport.
GetPort
();
326
m_connected
=
true
;
327
NotifyConnectionSucceeded
();
328
}
329
else
330
{
331
return
-1;
332
}
333
334
return
0;
335
}
336
337
int
338
UdpSocketImpl::Listen
(
void
)
339
{
340
m_errno
=
Socket::ERROR_OPNOTSUPP
;
341
return
-1;
342
}
343
344
int
345
UdpSocketImpl::Send
(
Ptr<Packet>
p, uint32_t flags)
346
{
347
NS_LOG_FUNCTION
(
this
<< p << flags);
348
349
if
(!
m_connected
)
350
{
351
m_errno
=
ERROR_NOTCONN
;
352
return
-1;
353
}
354
355
return
DoSend
(p);
356
}
357
358
int
359
UdpSocketImpl::DoSend
(
Ptr<Packet>
p)
360
{
361
NS_LOG_FUNCTION
(
this
<< p);
362
if
((
m_endPoint
== 0) && (
InetSocketAddress::IsMatchingType
(
m_defaultAddress
) ==
true
))
363
{
364
if
(
Bind
() == -1)
365
{
366
NS_ASSERT
(
m_endPoint
== 0);
367
return
-1;
368
}
369
NS_ASSERT
(
m_endPoint
!= 0);
370
}
371
else
if
((
m_endPoint6
== 0) && (
Inet6SocketAddress::IsMatchingType
(
m_defaultAddress
) ==
true
))
372
{
373
if
(
Bind6
() == -1)
374
{
375
NS_ASSERT
(
m_endPoint6
== 0);
376
return
-1;
377
}
378
NS_ASSERT
(
m_endPoint6
!= 0);
379
}
380
if
(
m_shutdownSend
)
381
{
382
m_errno
=
ERROR_SHUTDOWN
;
383
return
-1;
384
}
385
386
return
DoSendTo
(p, (
const
Address
)
m_defaultAddress
);
387
}
388
389
int
390
UdpSocketImpl::DoSendTo
(
Ptr<Packet>
p,
const
Address
&address)
391
{
392
NS_LOG_FUNCTION
(
this
<< p << address);
393
394
if
(!
m_connected
)
395
{
396
NS_LOG_LOGIC
(
"Not connected"
);
397
if
(
InetSocketAddress::IsMatchingType
(address) ==
true
)
398
{
399
InetSocketAddress
transport =
InetSocketAddress::ConvertFrom
(address);
400
Ipv4Address
ipv4 = transport.
GetIpv4
();
401
uint16_t
port
= transport.
GetPort
();
402
return
DoSendTo
(p, ipv4, port);
403
}
404
else
if
(
Inet6SocketAddress::IsMatchingType
(address) ==
true
)
405
{
406
Inet6SocketAddress
transport =
Inet6SocketAddress::ConvertFrom
(address);
407
Ipv6Address
ipv6 = transport.
GetIpv6
();
408
uint16_t
port
= transport.
GetPort
();
409
return
DoSendTo
(p, ipv6, port);
410
}
411
else
412
{
413
return
-1;
414
}
415
}
416
else
417
{
418
// connected UDP socket must use default addresses
419
NS_LOG_LOGIC
(
"Connected"
);
420
if
(
Ipv4Address::IsMatchingType
(
m_defaultAddress
))
421
{
422
return
DoSendTo
(p,
Ipv4Address::ConvertFrom
(
m_defaultAddress
),
m_defaultPort
);
423
}
424
else
if
(
Ipv6Address::IsMatchingType
(
m_defaultAddress
))
425
{
426
return
DoSendTo
(p,
Ipv6Address::ConvertFrom
(
m_defaultAddress
),
m_defaultPort
);
427
}
428
}
429
m_errno
=
ERROR_AFNOSUPPORT
;
430
return
(-1);
431
}
432
433
int
434
UdpSocketImpl::DoSendTo
(
Ptr<Packet>
p,
Ipv4Address
dest, uint16_t
port
)
435
{
436
NS_LOG_FUNCTION
(
this
<< p << dest << port);
437
if
(
m_boundnetdevice
)
438
{
439
NS_LOG_LOGIC
(
"Bound interface number "
<<
m_boundnetdevice
->
GetIfIndex
());
440
}
441
if
(
m_endPoint
== 0)
442
{
443
if
(
Bind
() == -1)
444
{
445
NS_ASSERT
(
m_endPoint
== 0);
446
return
-1;
447
}
448
NS_ASSERT
(
m_endPoint
!= 0);
449
}
450
if
(
m_shutdownSend
)
451
{
452
m_errno
=
ERROR_SHUTDOWN
;
453
return
-1;
454
}
455
456
if
(p->
GetSize
() >
GetTxAvailable
() )
457
{
458
m_errno
=
ERROR_MSGSIZE
;
459
return
-1;
460
}
461
462
if
(
IsManualIpTos
())
463
{
464
SocketIpTosTag
ipTosTag;
465
ipTosTag.
SetTos
(
GetIpTos
());
466
p->
AddPacketTag
(ipTosTag);
467
}
468
469
Ptr<Ipv4>
ipv4 =
m_node
->
GetObject
<
Ipv4
> ();
470
471
// Locally override the IP TTL for this socket
472
// We cannot directly modify the TTL at this stage, so we set a Packet tag
473
// The destination can be either multicast, unicast/anycast, or
474
// either all-hosts broadcast or limited (subnet-directed) broadcast.
475
// For the latter two broadcast types, the TTL will later be set to one
476
// irrespective of what is set in these socket options. So, this tagging
477
// may end up setting the TTL of a limited broadcast packet to be
478
// the same as a unicast, but it will be fixed further down the stack
479
if
(
m_ipMulticastTtl
!= 0 && dest.
IsMulticast
())
480
{
481
SocketIpTtlTag
tag;
482
tag.
SetTtl
(
m_ipMulticastTtl
);
483
p->
AddPacketTag
(tag);
484
}
485
else
if
(
IsManualIpTtl
() &&
GetIpTtl
() != 0 && !dest.
IsMulticast
() && !dest.
IsBroadcast
())
486
{
487
SocketIpTtlTag
tag;
488
tag.
SetTtl
(
GetIpTtl
());
489
p->
AddPacketTag
(tag);
490
}
491
{
492
SocketSetDontFragmentTag
tag;
493
bool
found = p->
RemovePacketTag
(tag);
494
if
(!found)
495
{
496
if
(
m_mtuDiscover
)
497
{
498
tag.
Enable
();
499
}
500
else
501
{
502
tag.
Disable
();
503
}
504
p->
AddPacketTag
(tag);
505
}
506
}
507
//
508
// If dest is set to the limited broadcast address (all ones),
509
// convert it to send a copy of the packet out of every
510
// interface as a subnet-directed broadcast.
511
// Exception: if the interface has a /32 address, there is no
512
// valid subnet-directed broadcast, so send it as limited broadcast
513
// Note also that some systems will only send limited broadcast packets
514
// out of the "default" interface; here we send it out all interfaces
515
//
516
if
(dest.
IsBroadcast
())
517
{
518
if
(!
m_allowBroadcast
)
519
{
520
m_errno
=
ERROR_OPNOTSUPP
;
521
return
-1;
522
}
523
NS_LOG_LOGIC
(
"Limited broadcast start."
);
524
for
(uint32_t i = 0; i < ipv4->
GetNInterfaces
(); i++ )
525
{
526
// Get the primary address
527
Ipv4InterfaceAddress
iaddr = ipv4->
GetAddress
(i, 0);
528
Ipv4Address
addri = iaddr.
GetLocal
();
529
if
(addri ==
Ipv4Address
(
"127.0.0.1"
))
530
continue
;
531
// Check if interface-bound socket
532
if
(
m_boundnetdevice
)
533
{
534
if
(ipv4->
GetNetDevice
(i) !=
m_boundnetdevice
)
535
continue
;
536
}
537
Ipv4Mask
maski = iaddr.
GetMask
();
538
if
(maski ==
Ipv4Mask::GetOnes
())
539
{
540
// if the network mask is 255.255.255.255, do not convert dest
541
NS_LOG_LOGIC
(
"Sending one copy from "
<< addri <<
" to "
<< dest
542
<<
" (mask is "
<< maski <<
")"
);
543
m_udp
->
Send
(p->
Copy
(), addri, dest,
544
m_endPoint
->
GetLocalPort
(),
port
);
545
NotifyDataSent
(p->
GetSize
());
546
NotifySend
(
GetTxAvailable
());
547
}
548
else
549
{
550
// Convert to subnet-directed broadcast
551
Ipv4Address
bcast = addri.
GetSubnetDirectedBroadcast
(maski);
552
NS_LOG_LOGIC
(
"Sending one copy from "
<< addri <<
" to "
<< bcast
553
<<
" (mask is "
<< maski <<
")"
);
554
m_udp
->
Send
(p->
Copy
(), addri, bcast,
555
m_endPoint
->
GetLocalPort
(),
port
);
556
NotifyDataSent
(p->
GetSize
());
557
NotifySend
(
GetTxAvailable
());
558
}
559
}
560
NS_LOG_LOGIC
(
"Limited broadcast end."
);
561
return
p->
GetSize
();
562
}
563
else
if
(
m_endPoint
->
GetLocalAddress
() !=
Ipv4Address::GetAny
())
564
{
565
m_udp
->
Send
(p->
Copy
(),
m_endPoint
->
GetLocalAddress
(), dest,
566
m_endPoint
->
GetLocalPort
(),
port
, 0);
567
NotifyDataSent
(p->
GetSize
());
568
NotifySend
(
GetTxAvailable
());
569
return
p->
GetSize
();
570
}
571
else
if
(ipv4->
GetRoutingProtocol
() != 0)
572
{
573
Ipv4Header
header;
574
header.
SetDestination
(dest);
575
header.
SetProtocol
(
UdpL4Protocol::PROT_NUMBER
);
576
Socket::SocketErrno
errno_;
577
Ptr<Ipv4Route>
route;
578
Ptr<NetDevice>
oif =
m_boundnetdevice
;
//specify non-zero if bound to a specific device
579
// TBD-- we could cache the route and just check its validity
580
route = ipv4->
GetRoutingProtocol
()->
RouteOutput
(p, header, oif, errno_);
581
if
(route != 0)
582
{
583
NS_LOG_LOGIC
(
"Route exists"
);
584
if
(!
m_allowBroadcast
)
585
{
586
uint32_t outputIfIndex = ipv4->
GetInterfaceForDevice
(route->
GetOutputDevice
());
587
uint32_t ifNAddr = ipv4->
GetNAddresses
(outputIfIndex);
588
for
(uint32_t addrI = 0; addrI < ifNAddr; ++addrI)
589
{
590
Ipv4InterfaceAddress
ifAddr = ipv4->
GetAddress
(outputIfIndex, addrI);
591
if
(dest == ifAddr.
GetBroadcast
())
592
{
593
m_errno
=
ERROR_OPNOTSUPP
;
594
return
-1;
595
}
596
}
597
}
598
599
header.
SetSource
(route->
GetSource
());
600
m_udp
->
Send
(p->
Copy
(), header.
GetSource
(), header.
GetDestination
(),
601
m_endPoint
->
GetLocalPort
(),
port
, route);
602
NotifyDataSent
(p->
GetSize
());
603
return
p->
GetSize
();
604
}
605
else
606
{
607
NS_LOG_LOGIC
(
"No route to destination"
);
608
NS_LOG_ERROR
(errno_);
609
m_errno
= errno_;
610
return
-1;
611
}
612
}
613
else
614
{
615
NS_LOG_ERROR
(
"ERROR_NOROUTETOHOST"
);
616
m_errno
=
ERROR_NOROUTETOHOST
;
617
return
-1;
618
}
619
620
return
0;
621
}
622
623
int
624
UdpSocketImpl::DoSendTo
(
Ptr<Packet>
p,
Ipv6Address
dest, uint16_t
port
)
625
{
626
NS_LOG_FUNCTION
(
this
<< p << dest << port);
627
628
if
(dest.
IsIpv4MappedAddress
())
629
{
630
return
(
DoSendTo
(p, dest.
GetIpv4MappedAddress
(),
port
));
631
}
632
if
(
m_boundnetdevice
)
633
{
634
NS_LOG_LOGIC
(
"Bound interface number "
<<
m_boundnetdevice
->
GetIfIndex
());
635
}
636
if
(
m_endPoint6
== 0)
637
{
638
if
(
Bind6
() == -1)
639
{
640
NS_ASSERT
(
m_endPoint6
== 0);
641
return
-1;
642
}
643
NS_ASSERT
(
m_endPoint6
!= 0);
644
}
645
if
(
m_shutdownSend
)
646
{
647
m_errno
=
ERROR_SHUTDOWN
;
648
return
-1;
649
}
650
651
if
(p->
GetSize
() >
GetTxAvailable
() )
652
{
653
m_errno
=
ERROR_MSGSIZE
;
654
return
-1;
655
}
656
657
if
(
IsManualIpv6Tclass
())
658
{
659
SocketIpv6TclassTag
ipTclassTag;
660
ipTclassTag.
SetTclass
(
GetIpv6Tclass
());
661
p->
AddPacketTag
(ipTclassTag);
662
}
663
664
Ptr<Ipv6>
ipv6 =
m_node
->
GetObject
<
Ipv6
> ();
665
666
// Locally override the IP TTL for this socket
667
// We cannot directly modify the TTL at this stage, so we set a Packet tag
668
// The destination can be either multicast, unicast/anycast, or
669
// either all-hosts broadcast or limited (subnet-directed) broadcast.
670
// For the latter two broadcast types, the TTL will later be set to one
671
// irrespective of what is set in these socket options. So, this tagging
672
// may end up setting the TTL of a limited broadcast packet to be
673
// the same as a unicast, but it will be fixed further down the stack
674
if
(
m_ipMulticastTtl
!= 0 && dest.
IsMulticast
())
675
{
676
SocketIpv6HopLimitTag
tag;
677
tag.
SetHopLimit
(
m_ipMulticastTtl
);
678
p->
AddPacketTag
(tag);
679
}
680
else
if
(
IsManualIpv6HopLimit
() &&
GetIpv6HopLimit
() != 0 && !dest.
IsMulticast
())
681
{
682
SocketIpv6HopLimitTag
tag;
683
tag.
SetHopLimit
(
GetIpv6HopLimit
());
684
p->
AddPacketTag
(tag);
685
}
686
// There is no analgous to an IPv4 broadcast address in IPv6.
687
// Instead, we use a set of link-local, site-local, and global
688
// multicast addresses. The Ipv6 routing layers should all
689
// provide an interface-specific route to these addresses such
690
// that we can treat these multicast addresses as "not broadcast"
691
692
if
(
m_endPoint6
->
GetLocalAddress
() !=
Ipv6Address::GetAny
())
693
{
694
m_udp
->
Send
(p->
Copy
(),
m_endPoint6
->
GetLocalAddress
(), dest,
695
m_endPoint6
->
GetLocalPort
(),
port
, 0);
696
NotifyDataSent
(p->
GetSize
());
697
NotifySend
(
GetTxAvailable
());
698
return
p->
GetSize
();
699
}
700
else
if
(ipv6->
GetRoutingProtocol
() != 0)
701
{
702
Ipv6Header
header;
703
header.
SetDestinationAddress
(dest);
704
header.
SetNextHeader
(
UdpL4Protocol::PROT_NUMBER
);
705
Socket::SocketErrno
errno_;
706
Ptr<Ipv6Route>
route;
707
Ptr<NetDevice>
oif =
m_boundnetdevice
;
//specify non-zero if bound to a specific device
708
// TBD-- we could cache the route and just check its validity
709
route = ipv6->
GetRoutingProtocol
()->
RouteOutput
(p, header, oif, errno_);
710
if
(route != 0)
711
{
712
NS_LOG_LOGIC
(
"Route exists"
);
713
header.
SetSourceAddress
(route->GetSource ());
714
m_udp
->
Send
(p->
Copy
(), header.
GetSourceAddress
(), header.
GetDestinationAddress
(),
715
m_endPoint6
->
GetLocalPort
(),
port
, route);
716
NotifyDataSent
(p->
GetSize
());
717
return
p->
GetSize
();
718
}
719
else
720
{
721
NS_LOG_LOGIC
(
"No route to destination"
);
722
NS_LOG_ERROR
(errno_);
723
m_errno
= errno_;
724
return
-1;
725
}
726
}
727
else
728
{
729
NS_LOG_ERROR
(
"ERROR_NOROUTETOHOST"
);
730
m_errno
=
ERROR_NOROUTETOHOST
;
731
return
-1;
732
}
733
734
return
0;
735
}
736
737
// XXX maximum message size for UDP broadcast is limited by MTU
738
// size of underlying link; we are not checking that now.
739
uint32_t
740
UdpSocketImpl::GetTxAvailable
(
void
)
const
741
{
742
NS_LOG_FUNCTION_NOARGS
();
743
// No finite send buffer is modelled, but we must respect
744
// the maximum size of an IP datagram (65535 bytes - headers).
745
return
MAX_IPV4_UDP_DATAGRAM_SIZE
;
746
}
747
748
int
749
UdpSocketImpl::SendTo
(
Ptr<Packet>
p, uint32_t flags,
const
Address
&address)
750
{
751
NS_LOG_FUNCTION
(
this
<< p << flags << address);
752
if
(
InetSocketAddress::IsMatchingType
(address))
753
{
754
if
(
IsManualIpTos
())
755
{
756
SocketIpTosTag
ipTosTag;
757
ipTosTag.
SetTos
(
GetIpTos
());
758
p->
AddPacketTag
(ipTosTag);
759
}
760
761
InetSocketAddress
transport =
InetSocketAddress::ConvertFrom
(address);
762
Ipv4Address
ipv4 = transport.
GetIpv4
();
763
uint16_t
port
= transport.
GetPort
();
764
return
DoSendTo
(p, ipv4, port);
765
}
766
else
if
(
Inet6SocketAddress::IsMatchingType
(address))
767
{
768
if
(
IsManualIpv6Tclass
())
769
{
770
SocketIpv6TclassTag
ipTclassTag;
771
ipTclassTag.
SetTclass
(
GetIpv6Tclass
());
772
p->
AddPacketTag
(ipTclassTag);
773
}
774
775
Inet6SocketAddress
transport =
Inet6SocketAddress::ConvertFrom
(address);
776
Ipv6Address
ipv6 = transport.
GetIpv6
();
777
uint16_t
port
= transport.
GetPort
();
778
return
DoSendTo
(p, ipv6, port);
779
}
780
return
-1;
781
}
782
783
uint32_t
784
UdpSocketImpl::GetRxAvailable
(
void
)
const
785
{
786
NS_LOG_FUNCTION_NOARGS
();
787
// We separately maintain this state to avoid walking the queue
788
// every time this might be called
789
return
m_rxAvailable
;
790
}
791
792
Ptr<Packet>
793
UdpSocketImpl::Recv
(uint32_t maxSize, uint32_t flags)
794
{
795
NS_LOG_FUNCTION
(
this
<< maxSize << flags);
796
if
(
m_deliveryQueue
.empty () )
797
{
798
m_errno
=
ERROR_AGAIN
;
799
return
0;
800
}
801
Ptr<Packet>
p =
m_deliveryQueue
.front ();
802
if
(p->
GetSize
() <= maxSize)
803
{
804
m_deliveryQueue
.pop ();
805
m_rxAvailable
-= p->
GetSize
();
806
}
807
else
808
{
809
p = 0;
810
}
811
return
p;
812
}
813
814
Ptr<Packet>
815
UdpSocketImpl::RecvFrom
(uint32_t maxSize, uint32_t flags,
816
Address
&fromAddress)
817
{
818
NS_LOG_FUNCTION
(
this
<< maxSize << flags);
819
Ptr<Packet>
packet =
Recv
(maxSize, flags);
820
if
(packet != 0)
821
{
822
SocketAddressTag
tag;
823
bool
found;
824
found = packet->
PeekPacketTag
(tag);
825
NS_ASSERT
(found);
826
fromAddress = tag.
GetAddress
();
827
}
828
return
packet;
829
}
830
831
int
832
UdpSocketImpl::GetSockName
(
Address
&address)
const
833
{
834
NS_LOG_FUNCTION_NOARGS
();
835
if
(
m_endPoint
!= 0)
836
{
837
address =
InetSocketAddress
(
m_endPoint
->
GetLocalAddress
(),
m_endPoint
->
GetLocalPort
());
838
}
839
else
840
{
841
// It is possible to call this method on a socket without a name
842
// in which case, behavior is unspecified
843
address =
InetSocketAddress
(
Ipv4Address::GetZero
(), 0);
844
}
845
return
0;
846
}
847
848
int
849
UdpSocketImpl::MulticastJoinGroup
(uint32_t interface,
const
Address
&groupAddress)
850
{
851
NS_LOG_FUNCTION
(interface << groupAddress);
852
/*
853
1) sanity check interface
854
2) sanity check that it has not been called yet on this interface/group
855
3) determine address family of groupAddress
856
4) locally store a list of (interface, groupAddress)
857
5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
858
*/
859
return
0;
860
}
861
862
int
863
UdpSocketImpl::MulticastLeaveGroup
(uint32_t interface,
const
Address
&groupAddress)
864
{
865
NS_LOG_FUNCTION
(interface << groupAddress);
866
/*
867
1) sanity check interface
868
2) determine address family of groupAddress
869
3) delete from local list of (interface, groupAddress); raise a LOG_WARN
870
if not already present (but return 0)
871
5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
872
*/
873
return
0;
874
}
875
876
void
877
UdpSocketImpl::BindToNetDevice
(
Ptr<NetDevice>
netdevice)
878
{
879
NS_LOG_FUNCTION
(netdevice);
880
Socket::BindToNetDevice
(netdevice);
// Includes sanity check
881
if
(
m_endPoint
== 0)
882
{
883
if
(
Bind
() == -1)
884
{
885
NS_ASSERT
(
m_endPoint
== 0);
886
return
;
887
}
888
NS_ASSERT
(
m_endPoint
!= 0);
889
}
890
m_endPoint
->
BindToNetDevice
(netdevice);
891
return
;
892
}
893
894
void
895
UdpSocketImpl::ForwardUp
(
Ptr<Packet>
packet,
Ipv4Header
header, uint16_t
port
,
896
Ptr<Ipv4Interface>
incomingInterface)
897
{
898
NS_LOG_FUNCTION
(
this
<< packet << header << port);
899
900
if
(
m_shutdownRecv
)
901
{
902
return
;
903
}
904
905
// Should check via getsockopt ()..
906
if
(
IsRecvPktInfo
())
907
{
908
Ipv4PacketInfoTag
tag;
909
packet->
RemovePacketTag
(tag);
910
tag.
SetRecvIf
(incomingInterface->
GetDevice
()->
GetIfIndex
());
911
packet->
AddPacketTag
(tag);
912
}
913
914
//Check only version 4 options
915
if
(
IsIpRecvTos
())
916
{
917
SocketIpTosTag
ipTosTag;
918
ipTosTag.
SetTos
(header.
GetTos
());
919
packet->
AddPacketTag
(ipTosTag);
920
}
921
922
if
(
IsIpRecvTtl
())
923
{
924
SocketIpTtlTag
ipTtlTag;
925
ipTtlTag.
SetTtl
(header.
GetTtl
());
926
packet->
AddPacketTag
(ipTtlTag);
927
}
928
929
if
((
m_rxAvailable
+ packet->
GetSize
()) <=
m_rcvBufSize
)
930
{
931
Address
address =
InetSocketAddress
(header.
GetSource
(),
port
);
932
SocketAddressTag
tag;
933
tag.
SetAddress
(address);
934
packet->
AddPacketTag
(tag);
935
m_deliveryQueue
.push (packet);
936
m_rxAvailable
+= packet->
GetSize
();
937
NotifyDataRecv
();
938
}
939
else
940
{
941
// In general, this case should not occur unless the
942
// receiving application reads data from this socket slowly
943
// in comparison to the arrival rate
944
//
945
// drop and trace packet
946
NS_LOG_WARN
(
"No receive buffer space available. Drop."
);
947
m_dropTrace
(packet);
948
}
949
}
950
951
void
952
UdpSocketImpl::ForwardUp6
(
Ptr<Packet>
packet,
Ipv6Header
header, uint16_t
port
)
953
{
954
NS_LOG_FUNCTION
(
this
<< packet << header.
GetSourceAddress
() <<
port
);
955
956
if
(
m_shutdownRecv
)
957
{
958
return
;
959
}
960
961
962
//Check only version 6 options
963
if
(
IsIpv6RecvTclass
())
964
{
965
SocketIpv6TclassTag
ipTclassTag;
966
ipTclassTag.
SetTclass
(header.
GetTrafficClass
());
967
packet->
AddPacketTag
(ipTclassTag);
968
}
969
970
if
(
IsIpv6RecvHopLimit
())
971
{
972
SocketIpv6HopLimitTag
ipHopLimitTag;
973
ipHopLimitTag.
SetHopLimit
(header.
GetHopLimit
());
974
packet->
AddPacketTag
(ipHopLimitTag);
975
}
976
977
if
((
m_rxAvailable
+ packet->
GetSize
()) <=
m_rcvBufSize
)
978
{
979
Address
address =
Inet6SocketAddress
(header.
GetSourceAddress
(),
port
);
980
SocketAddressTag
tag;
981
tag.
SetAddress
(address);
982
packet->
AddPacketTag
(tag);
983
m_deliveryQueue
.push (packet);
984
m_rxAvailable
+= packet->
GetSize
();
985
NotifyDataRecv
();
986
}
987
else
988
{
989
// In general, this case should not occur unless the
990
// receiving application reads data from this socket slowly
991
// in comparison to the arrival rate
992
//
993
// drop and trace packet
994
NS_LOG_WARN
(
"No receive buffer space available. Drop."
);
995
m_dropTrace
(packet);
996
}
997
}
998
999
void
1000
UdpSocketImpl::ForwardIcmp
(
Ipv4Address
icmpSource, uint8_t icmpTtl,
1001
uint8_t icmpType, uint8_t icmpCode,
1002
uint32_t icmpInfo)
1003
{
1004
NS_LOG_FUNCTION
(
this
<< icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1005
(uint32_t)icmpCode << icmpInfo);
1006
if
(!
m_icmpCallback
.
IsNull
())
1007
{
1008
m_icmpCallback
(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1009
}
1010
}
1011
1012
void
1013
UdpSocketImpl::ForwardIcmp6
(
Ipv6Address
icmpSource, uint8_t icmpTtl,
1014
uint8_t icmpType, uint8_t icmpCode,
1015
uint32_t icmpInfo)
1016
{
1017
NS_LOG_FUNCTION
(
this
<< icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1018
(uint32_t)icmpCode << icmpInfo);
1019
if
(!
m_icmpCallback6
.
IsNull
())
1020
{
1021
m_icmpCallback6
(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1022
}
1023
}
1024
1025
void
1026
UdpSocketImpl::SetRcvBufSize
(uint32_t size)
1027
{
1028
m_rcvBufSize
= size;
1029
}
1030
1031
uint32_t
1032
UdpSocketImpl::GetRcvBufSize
(
void
)
const
1033
{
1034
return
m_rcvBufSize
;
1035
}
1036
1037
void
1038
UdpSocketImpl::SetIpMulticastTtl
(uint8_t ipTtl)
1039
{
1040
m_ipMulticastTtl
= ipTtl;
1041
}
1042
1043
uint8_t
1044
UdpSocketImpl::GetIpMulticastTtl
(
void
)
const
1045
{
1046
return
m_ipMulticastTtl
;
1047
}
1048
1049
void
1050
UdpSocketImpl::SetIpMulticastIf
(int32_t ipIf)
1051
{
1052
m_ipMulticastIf
= ipIf;
1053
}
1054
1055
int32_t
1056
UdpSocketImpl::GetIpMulticastIf
(
void
)
const
1057
{
1058
return
m_ipMulticastIf
;
1059
}
1060
1061
void
1062
UdpSocketImpl::SetIpMulticastLoop
(
bool
loop)
1063
{
1064
m_ipMulticastLoop
= loop;
1065
}
1066
1067
bool
1068
UdpSocketImpl::GetIpMulticastLoop
(
void
)
const
1069
{
1070
return
m_ipMulticastLoop
;
1071
}
1072
1073
void
1074
UdpSocketImpl::SetMtuDiscover
(
bool
discover)
1075
{
1076
m_mtuDiscover
= discover;
1077
}
1078
bool
1079
UdpSocketImpl::GetMtuDiscover
(
void
)
const
1080
{
1081
return
m_mtuDiscover
;
1082
}
1083
1084
bool
1085
UdpSocketImpl::SetAllowBroadcast
(
bool
allowBroadcast)
1086
{
1087
m_allowBroadcast
= allowBroadcast;
1088
return
true
;
1089
}
1090
1091
bool
1092
UdpSocketImpl::GetAllowBroadcast
()
const
1093
{
1094
return
m_allowBroadcast
;
1095
}
1096
1097
1098
}
// namespace ns3
src
internet
model
udp-socket-impl.cc
Generated on Tue May 14 2013 11:08:23 for ns-3 by
1.8.1.2