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
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
738
// maximum message size for UDP broadcast is limited by MTU
739
// size of underlying link; we are not checking that now.
741
uint32_t
742
UdpSocketImpl::GetTxAvailable
(
void
)
const
743
{
744
NS_LOG_FUNCTION_NOARGS
();
745
// No finite send buffer is modelled, but we must respect
746
// the maximum size of an IP datagram (65535 bytes - headers).
747
return
MAX_IPV4_UDP_DATAGRAM_SIZE
;
748
}
749
750
int
751
UdpSocketImpl::SendTo
(
Ptr<Packet>
p, uint32_t flags,
const
Address
&
address
)
752
{
753
NS_LOG_FUNCTION
(
this
<< p << flags << address);
754
if
(
InetSocketAddress::IsMatchingType
(address))
755
{
756
if
(
IsManualIpTos
())
757
{
758
SocketIpTosTag
ipTosTag;
759
ipTosTag.
SetTos
(
GetIpTos
());
760
p->
AddPacketTag
(ipTosTag);
761
}
762
763
InetSocketAddress
transport =
InetSocketAddress::ConvertFrom
(address);
764
Ipv4Address
ipv4 = transport.
GetIpv4
();
765
uint16_t
port
= transport.
GetPort
();
766
return
DoSendTo
(p, ipv4, port);
767
}
768
else
if
(
Inet6SocketAddress::IsMatchingType
(address))
769
{
770
if
(
IsManualIpv6Tclass
())
771
{
772
SocketIpv6TclassTag
ipTclassTag;
773
ipTclassTag.
SetTclass
(
GetIpv6Tclass
());
774
p->
AddPacketTag
(ipTclassTag);
775
}
776
777
Inet6SocketAddress
transport =
Inet6SocketAddress::ConvertFrom
(address);
778
Ipv6Address
ipv6 = transport.
GetIpv6
();
779
uint16_t
port
= transport.
GetPort
();
780
return
DoSendTo
(p, ipv6, port);
781
}
782
return
-1;
783
}
784
785
uint32_t
786
UdpSocketImpl::GetRxAvailable
(
void
)
const
787
{
788
NS_LOG_FUNCTION_NOARGS
();
789
// We separately maintain this state to avoid walking the queue
790
// every time this might be called
791
return
m_rxAvailable
;
792
}
793
794
Ptr<Packet>
795
UdpSocketImpl::Recv
(uint32_t maxSize, uint32_t flags)
796
{
797
NS_LOG_FUNCTION
(
this
<< maxSize << flags);
798
if
(
m_deliveryQueue
.empty () )
799
{
800
m_errno
=
ERROR_AGAIN
;
801
return
0;
802
}
803
Ptr<Packet>
p =
m_deliveryQueue
.front ();
804
if
(p->
GetSize
() <= maxSize)
805
{
806
m_deliveryQueue
.pop ();
807
m_rxAvailable
-= p->
GetSize
();
808
}
809
else
810
{
811
p = 0;
812
}
813
return
p;
814
}
815
816
Ptr<Packet>
817
UdpSocketImpl::RecvFrom
(uint32_t maxSize, uint32_t flags,
818
Address
&fromAddress)
819
{
820
NS_LOG_FUNCTION
(
this
<< maxSize << flags);
821
Ptr<Packet>
packet =
Recv
(maxSize, flags);
822
if
(packet != 0)
823
{
824
SocketAddressTag
tag;
825
bool
found;
826
found = packet->
PeekPacketTag
(tag);
827
NS_ASSERT
(found);
828
fromAddress = tag.
GetAddress
();
829
}
830
return
packet;
831
}
832
833
int
834
UdpSocketImpl::GetSockName
(
Address
&
address
)
const
835
{
836
NS_LOG_FUNCTION_NOARGS
();
837
if
(
m_endPoint
!= 0)
838
{
839
address =
InetSocketAddress
(
m_endPoint
->
GetLocalAddress
(),
m_endPoint
->
GetLocalPort
());
840
}
841
else
842
{
843
// It is possible to call this method on a socket without a name
844
// in which case, behavior is unspecified
845
address =
InetSocketAddress
(
Ipv4Address::GetZero
(), 0);
846
}
847
return
0;
848
}
849
850
int
851
UdpSocketImpl::MulticastJoinGroup
(uint32_t interface,
const
Address
&groupAddress)
852
{
853
NS_LOG_FUNCTION
(interface << groupAddress);
854
/*
855
1) sanity check interface
856
2) sanity check that it has not been called yet on this interface/group
857
3) determine address family of groupAddress
858
4) locally store a list of (interface, groupAddress)
859
5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
860
*/
861
return
0;
862
}
863
864
int
865
UdpSocketImpl::MulticastLeaveGroup
(uint32_t interface,
const
Address
&groupAddress)
866
{
867
NS_LOG_FUNCTION
(interface << groupAddress);
868
/*
869
1) sanity check interface
870
2) determine address family of groupAddress
871
3) delete from local list of (interface, groupAddress); raise a LOG_WARN
872
if not already present (but return 0)
873
5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
874
*/
875
return
0;
876
}
877
878
void
879
UdpSocketImpl::BindToNetDevice
(
Ptr<NetDevice>
netdevice)
880
{
881
NS_LOG_FUNCTION
(netdevice);
882
Socket::BindToNetDevice
(netdevice);
// Includes sanity check
883
if
(
m_endPoint
== 0)
884
{
885
if
(
Bind
() == -1)
886
{
887
NS_ASSERT
(
m_endPoint
== 0);
888
return
;
889
}
890
NS_ASSERT
(
m_endPoint
!= 0);
891
}
892
m_endPoint
->
BindToNetDevice
(netdevice);
893
return
;
894
}
895
896
void
897
UdpSocketImpl::ForwardUp
(
Ptr<Packet>
packet,
Ipv4Header
header, uint16_t
port
,
898
Ptr<Ipv4Interface>
incomingInterface)
899
{
900
NS_LOG_FUNCTION
(
this
<< packet << header << port);
901
902
if
(
m_shutdownRecv
)
903
{
904
return
;
905
}
906
907
// Should check via getsockopt ()..
908
if
(
IsRecvPktInfo
())
909
{
910
Ipv4PacketInfoTag
tag;
911
packet->
RemovePacketTag
(tag);
912
tag.
SetRecvIf
(incomingInterface->
GetDevice
()->
GetIfIndex
());
913
packet->
AddPacketTag
(tag);
914
}
915
916
//Check only version 4 options
917
if
(
IsIpRecvTos
())
918
{
919
SocketIpTosTag
ipTosTag;
920
ipTosTag.
SetTos
(header.
GetTos
());
921
packet->
AddPacketTag
(ipTosTag);
922
}
923
924
if
(
IsIpRecvTtl
())
925
{
926
SocketIpTtlTag
ipTtlTag;
927
ipTtlTag.
SetTtl
(header.
GetTtl
());
928
packet->
AddPacketTag
(ipTtlTag);
929
}
930
931
if
((
m_rxAvailable
+ packet->
GetSize
()) <=
m_rcvBufSize
)
932
{
933
Address
address
=
InetSocketAddress
(header.
GetSource
(),
port
);
934
SocketAddressTag
tag;
935
tag.
SetAddress
(address);
936
packet->
AddPacketTag
(tag);
937
m_deliveryQueue
.push (packet);
938
m_rxAvailable
+= packet->
GetSize
();
939
NotifyDataRecv
();
940
}
941
else
942
{
943
// In general, this case should not occur unless the
944
// receiving application reads data from this socket slowly
945
// in comparison to the arrival rate
946
//
947
// drop and trace packet
948
NS_LOG_WARN
(
"No receive buffer space available. Drop."
);
949
m_dropTrace
(packet);
950
}
951
}
952
953
void
954
UdpSocketImpl::ForwardUp6
(
Ptr<Packet>
packet,
Ipv6Header
header, uint16_t
port
)
955
{
956
NS_LOG_FUNCTION
(
this
<< packet << header.
GetSourceAddress
() <<
port
);
957
958
if
(
m_shutdownRecv
)
959
{
960
return
;
961
}
962
963
964
//Check only version 6 options
965
if
(
IsIpv6RecvTclass
())
966
{
967
SocketIpv6TclassTag
ipTclassTag;
968
ipTclassTag.
SetTclass
(header.
GetTrafficClass
());
969
packet->
AddPacketTag
(ipTclassTag);
970
}
971
972
if
(
IsIpv6RecvHopLimit
())
973
{
974
SocketIpv6HopLimitTag
ipHopLimitTag;
975
ipHopLimitTag.
SetHopLimit
(header.
GetHopLimit
());
976
packet->
AddPacketTag
(ipHopLimitTag);
977
}
978
979
if
((
m_rxAvailable
+ packet->
GetSize
()) <=
m_rcvBufSize
)
980
{
981
Address
address
=
Inet6SocketAddress
(header.
GetSourceAddress
(),
port
);
982
SocketAddressTag
tag;
983
tag.
SetAddress
(address);
984
packet->
AddPacketTag
(tag);
985
m_deliveryQueue
.push (packet);
986
m_rxAvailable
+= packet->
GetSize
();
987
NotifyDataRecv
();
988
}
989
else
990
{
991
// In general, this case should not occur unless the
992
// receiving application reads data from this socket slowly
993
// in comparison to the arrival rate
994
//
995
// drop and trace packet
996
NS_LOG_WARN
(
"No receive buffer space available. Drop."
);
997
m_dropTrace
(packet);
998
}
999
}
1000
1001
void
1002
UdpSocketImpl::ForwardIcmp
(
Ipv4Address
icmpSource, uint8_t icmpTtl,
1003
uint8_t icmpType, uint8_t icmpCode,
1004
uint32_t icmpInfo)
1005
{
1006
NS_LOG_FUNCTION
(
this
<< icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1007
(uint32_t)icmpCode << icmpInfo);
1008
if
(!
m_icmpCallback
.
IsNull
())
1009
{
1010
m_icmpCallback
(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1011
}
1012
}
1013
1014
void
1015
UdpSocketImpl::ForwardIcmp6
(
Ipv6Address
icmpSource, uint8_t icmpTtl,
1016
uint8_t icmpType, uint8_t icmpCode,
1017
uint32_t icmpInfo)
1018
{
1019
NS_LOG_FUNCTION
(
this
<< icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1020
(uint32_t)icmpCode << icmpInfo);
1021
if
(!
m_icmpCallback6
.
IsNull
())
1022
{
1023
m_icmpCallback6
(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1024
}
1025
}
1026
1027
void
1028
UdpSocketImpl::SetRcvBufSize
(uint32_t size)
1029
{
1030
m_rcvBufSize
= size;
1031
}
1032
1033
uint32_t
1034
UdpSocketImpl::GetRcvBufSize
(
void
)
const
1035
{
1036
return
m_rcvBufSize
;
1037
}
1038
1039
void
1040
UdpSocketImpl::SetIpMulticastTtl
(uint8_t ipTtl)
1041
{
1042
m_ipMulticastTtl
= ipTtl;
1043
}
1044
1045
uint8_t
1046
UdpSocketImpl::GetIpMulticastTtl
(
void
)
const
1047
{
1048
return
m_ipMulticastTtl
;
1049
}
1050
1051
void
1052
UdpSocketImpl::SetIpMulticastIf
(int32_t ipIf)
1053
{
1054
m_ipMulticastIf
= ipIf;
1055
}
1056
1057
int32_t
1058
UdpSocketImpl::GetIpMulticastIf
(
void
)
const
1059
{
1060
return
m_ipMulticastIf
;
1061
}
1062
1063
void
1064
UdpSocketImpl::SetIpMulticastLoop
(
bool
loop)
1065
{
1066
m_ipMulticastLoop
= loop;
1067
}
1068
1069
bool
1070
UdpSocketImpl::GetIpMulticastLoop
(
void
)
const
1071
{
1072
return
m_ipMulticastLoop
;
1073
}
1074
1075
void
1076
UdpSocketImpl::SetMtuDiscover
(
bool
discover)
1077
{
1078
m_mtuDiscover
= discover;
1079
}
1080
bool
1081
UdpSocketImpl::GetMtuDiscover
(
void
)
const
1082
{
1083
return
m_mtuDiscover
;
1084
}
1085
1086
bool
1087
UdpSocketImpl::SetAllowBroadcast
(
bool
allowBroadcast)
1088
{
1089
m_allowBroadcast
= allowBroadcast;
1090
return
true
;
1091
}
1092
1093
bool
1094
UdpSocketImpl::GetAllowBroadcast
()
const
1095
{
1096
return
m_allowBroadcast
;
1097
}
1098
1099
1100
}
// namespace ns3
src
internet
model
udp-socket-impl.cc
Generated on Fri Aug 30 2013 01:42:52 for ns-3 by
1.8.1.2