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
return
DoSend
(p);
355
}
356
357
int
358
UdpSocketImpl::DoSend
(
Ptr<Packet>
p)
359
{
360
NS_LOG_FUNCTION
(
this
<< p);
361
if
((
m_endPoint
== 0) && (
InetSocketAddress::IsMatchingType
(
m_defaultAddress
) ==
true
))
362
{
363
if
(
Bind
() == -1)
364
{
365
NS_ASSERT
(
m_endPoint
== 0);
366
return
-1;
367
}
368
NS_ASSERT
(
m_endPoint
!= 0);
369
}
370
else
if
((
m_endPoint6
== 0) && (
Inet6SocketAddress::IsMatchingType
(
m_defaultAddress
) ==
true
))
371
{
372
if
(
Bind6
() == -1)
373
{
374
NS_ASSERT
(
m_endPoint6
== 0);
375
return
-1;
376
}
377
NS_ASSERT
(
m_endPoint6
!= 0);
378
}
379
if
(
m_shutdownSend
)
380
{
381
m_errno
=
ERROR_SHUTDOWN
;
382
return
-1;
383
}
384
385
return
DoSendTo
(p, (
const
Address
)
m_defaultAddress
);
386
}
387
388
int
389
UdpSocketImpl::DoSendTo
(
Ptr<Packet>
p,
const
Address
&address)
390
{
391
NS_LOG_FUNCTION
(
this
<< p << address);
392
393
if
(!
m_connected
)
394
{
395
NS_LOG_LOGIC
(
"Not connected"
);
396
if
(
InetSocketAddress::IsMatchingType
(address) ==
true
)
397
{
398
InetSocketAddress
transport =
InetSocketAddress::ConvertFrom
(address);
399
Ipv4Address
ipv4 = transport.
GetIpv4
();
400
uint16_t
port
= transport.
GetPort
();
401
return
DoSendTo
(p, ipv4, port);
402
}
403
else
if
(
Inet6SocketAddress::IsMatchingType
(address) ==
true
)
404
{
405
Inet6SocketAddress
transport =
Inet6SocketAddress::ConvertFrom
(address);
406
Ipv6Address
ipv6 = transport.
GetIpv6
();
407
uint16_t
port
= transport.
GetPort
();
408
return
DoSendTo
(p, ipv6, port);
409
}
410
else
411
{
412
return
-1;
413
}
414
}
415
else
416
{
417
// connected UDP socket must use default addresses
418
NS_LOG_LOGIC
(
"Connected"
);
419
if
(
Ipv4Address::IsMatchingType
(
m_defaultAddress
))
420
{
421
return
DoSendTo
(p,
Ipv4Address::ConvertFrom
(
m_defaultAddress
),
m_defaultPort
);
422
}
423
else
if
(
Ipv6Address::IsMatchingType
(
m_defaultAddress
))
424
{
425
return
DoSendTo
(p,
Ipv6Address::ConvertFrom
(
m_defaultAddress
),
m_defaultPort
);
426
}
427
}
428
m_errno
=
ERROR_AFNOSUPPORT
;
429
return
(-1);
430
}
431
432
int
433
UdpSocketImpl::DoSendTo
(
Ptr<Packet>
p,
Ipv4Address
dest, uint16_t
port
)
434
{
435
NS_LOG_FUNCTION
(
this
<< p << dest << port);
436
if
(
m_boundnetdevice
)
437
{
438
NS_LOG_LOGIC
(
"Bound interface number "
<<
m_boundnetdevice
->
GetIfIndex
());
439
}
440
if
(
m_endPoint
== 0)
441
{
442
if
(
Bind
() == -1)
443
{
444
NS_ASSERT
(
m_endPoint
== 0);
445
return
-1;
446
}
447
NS_ASSERT
(
m_endPoint
!= 0);
448
}
449
if
(
m_shutdownSend
)
450
{
451
m_errno
=
ERROR_SHUTDOWN
;
452
return
-1;
453
}
454
455
if
(p->
GetSize
() >
GetTxAvailable
() )
456
{
457
m_errno
=
ERROR_MSGSIZE
;
458
return
-1;
459
}
460
461
Ptr<Ipv4>
ipv4 =
m_node
->
GetObject
<
Ipv4
> ();
462
463
// Locally override the IP TTL for this socket
464
// We cannot directly modify the TTL at this stage, so we set a Packet tag
465
// The destination can be either multicast, unicast/anycast, or
466
// either all-hosts broadcast or limited (subnet-directed) broadcast.
467
// For the latter two broadcast types, the TTL will later be set to one
468
// irrespective of what is set in these socket options. So, this tagging
469
// may end up setting the TTL of a limited broadcast packet to be
470
// the same as a unicast, but it will be fixed further down the stack
471
if
(
m_ipMulticastTtl
!= 0 && dest.
IsMulticast
())
472
{
473
SocketIpTtlTag
tag;
474
tag.
SetTtl
(
m_ipMulticastTtl
);
475
p->
AddPacketTag
(tag);
476
}
477
else
if
(
m_ipTtl
!= 0 && !dest.
IsMulticast
() && !dest.
IsBroadcast
())
478
{
479
SocketIpTtlTag
tag;
480
tag.
SetTtl
(
m_ipTtl
);
481
p->
AddPacketTag
(tag);
482
}
483
{
484
SocketSetDontFragmentTag
tag;
485
bool
found = p->
RemovePacketTag
(tag);
486
if
(!found)
487
{
488
if
(
m_mtuDiscover
)
489
{
490
tag.
Enable
();
491
}
492
else
493
{
494
tag.
Disable
();
495
}
496
p->
AddPacketTag
(tag);
497
}
498
}
499
//
500
// If dest is set to the limited broadcast address (all ones),
501
// convert it to send a copy of the packet out of every
502
// interface as a subnet-directed broadcast.
503
// Exception: if the interface has a /32 address, there is no
504
// valid subnet-directed broadcast, so send it as limited broadcast
505
// Note also that some systems will only send limited broadcast packets
506
// out of the "default" interface; here we send it out all interfaces
507
//
508
if
(dest.
IsBroadcast
())
509
{
510
if
(!
m_allowBroadcast
)
511
{
512
m_errno
=
ERROR_OPNOTSUPP
;
513
return
-1;
514
}
515
NS_LOG_LOGIC
(
"Limited broadcast start."
);
516
for
(uint32_t i = 0; i < ipv4->
GetNInterfaces
(); i++ )
517
{
518
// Get the primary address
519
Ipv4InterfaceAddress
iaddr = ipv4->
GetAddress
(i, 0);
520
Ipv4Address
addri = iaddr.
GetLocal
();
521
if
(addri ==
Ipv4Address
(
"127.0.0.1"
))
522
continue
;
523
// Check if interface-bound socket
524
if
(
m_boundnetdevice
)
525
{
526
if
(ipv4->
GetNetDevice
(i) !=
m_boundnetdevice
)
527
continue
;
528
}
529
Ipv4Mask
maski = iaddr.
GetMask
();
530
if
(maski ==
Ipv4Mask::GetOnes
())
531
{
532
// if the network mask is 255.255.255.255, do not convert dest
533
NS_LOG_LOGIC
(
"Sending one copy from "
<< addri <<
" to "
<< dest
534
<<
" (mask is "
<< maski <<
")"
);
535
m_udp
->
Send
(p->
Copy
(), addri, dest,
536
m_endPoint
->
GetLocalPort
(),
port
);
537
NotifyDataSent
(p->
GetSize
());
538
NotifySend
(
GetTxAvailable
());
539
}
540
else
541
{
542
// Convert to subnet-directed broadcast
543
Ipv4Address
bcast = addri.
GetSubnetDirectedBroadcast
(maski);
544
NS_LOG_LOGIC
(
"Sending one copy from "
<< addri <<
" to "
<< bcast
545
<<
" (mask is "
<< maski <<
")"
);
546
m_udp
->
Send
(p->
Copy
(), addri, bcast,
547
m_endPoint
->
GetLocalPort
(),
port
);
548
NotifyDataSent
(p->
GetSize
());
549
NotifySend
(
GetTxAvailable
());
550
}
551
}
552
NS_LOG_LOGIC
(
"Limited broadcast end."
);
553
return
p->
GetSize
();
554
}
555
else
if
(
m_endPoint
->
GetLocalAddress
() !=
Ipv4Address::GetAny
())
556
{
557
m_udp
->
Send
(p->
Copy
(),
m_endPoint
->
GetLocalAddress
(), dest,
558
m_endPoint
->
GetLocalPort
(),
port
, 0);
559
NotifyDataSent
(p->
GetSize
());
560
NotifySend
(
GetTxAvailable
());
561
return
p->
GetSize
();
562
}
563
else
if
(ipv4->
GetRoutingProtocol
() != 0)
564
{
565
Ipv4Header
header;
566
header.
SetDestination
(dest);
567
header.
SetProtocol
(
UdpL4Protocol::PROT_NUMBER
);
568
Socket::SocketErrno
errno_;
569
Ptr<Ipv4Route>
route;
570
Ptr<NetDevice>
oif =
m_boundnetdevice
;
//specify non-zero if bound to a specific device
571
// TBD-- we could cache the route and just check its validity
572
route = ipv4->
GetRoutingProtocol
()->
RouteOutput
(p, header, oif, errno_);
573
if
(route != 0)
574
{
575
NS_LOG_LOGIC
(
"Route exists"
);
576
if
(!
m_allowBroadcast
)
577
{
578
uint32_t outputIfIndex = ipv4->
GetInterfaceForDevice
(route->
GetOutputDevice
());
579
uint32_t ifNAddr = ipv4->
GetNAddresses
(outputIfIndex);
580
for
(uint32_t addrI = 0; addrI < ifNAddr; ++addrI)
581
{
582
Ipv4InterfaceAddress
ifAddr = ipv4->
GetAddress
(outputIfIndex, addrI);
583
if
(dest == ifAddr.
GetBroadcast
())
584
{
585
m_errno
=
ERROR_OPNOTSUPP
;
586
return
-1;
587
}
588
}
589
}
590
591
header.
SetSource
(route->
GetSource
());
592
m_udp
->
Send
(p->
Copy
(), header.
GetSource
(), header.
GetDestination
(),
593
m_endPoint
->
GetLocalPort
(),
port
, route);
594
NotifyDataSent
(p->
GetSize
());
595
return
p->
GetSize
();
596
}
597
else
598
{
599
NS_LOG_LOGIC
(
"No route to destination"
);
600
NS_LOG_ERROR
(errno_);
601
m_errno
= errno_;
602
return
-1;
603
}
604
}
605
else
606
{
607
NS_LOG_ERROR
(
"ERROR_NOROUTETOHOST"
);
608
m_errno
=
ERROR_NOROUTETOHOST
;
609
return
-1;
610
}
611
612
return
0;
613
}
614
615
int
616
UdpSocketImpl::DoSendTo
(
Ptr<Packet>
p,
Ipv6Address
dest, uint16_t
port
)
617
{
618
NS_LOG_FUNCTION
(
this
<< p << dest << port);
619
620
if
(dest.
IsIpv4MappedAddress
())
621
{
622
return
(
DoSendTo
(p, dest.
GetIpv4MappedAddress
(),
port
));
623
}
624
if
(
m_boundnetdevice
)
625
{
626
NS_LOG_LOGIC
(
"Bound interface number "
<<
m_boundnetdevice
->
GetIfIndex
());
627
}
628
if
(
m_endPoint6
== 0)
629
{
630
if
(
Bind6
() == -1)
631
{
632
NS_ASSERT
(
m_endPoint6
== 0);
633
return
-1;
634
}
635
NS_ASSERT
(
m_endPoint6
!= 0);
636
}
637
if
(
m_shutdownSend
)
638
{
639
m_errno
=
ERROR_SHUTDOWN
;
640
return
-1;
641
}
642
643
if
(p->
GetSize
() >
GetTxAvailable
() )
644
{
645
m_errno
=
ERROR_MSGSIZE
;
646
return
-1;
647
}
648
649
Ptr<Ipv6>
ipv6 =
m_node
->
GetObject
<
Ipv6
> ();
650
651
// Locally override the IP TTL for this socket
652
// We cannot directly modify the TTL at this stage, so we set a Packet tag
653
// The destination can be either multicast, unicast/anycast, or
654
// either all-hosts broadcast or limited (subnet-directed) broadcast.
655
// For the latter two broadcast types, the TTL will later be set to one
656
// irrespective of what is set in these socket options. So, this tagging
657
// may end up setting the TTL of a limited broadcast packet to be
658
// the same as a unicast, but it will be fixed further down the stack
659
if
(
m_ipMulticastTtl
!= 0 && dest.
IsMulticast
())
660
{
661
SocketIpTtlTag
tag;
662
tag.
SetTtl
(
m_ipMulticastTtl
);
663
p->
AddPacketTag
(tag);
664
}
665
else
if
(
m_ipTtl
!= 0 && !dest.
IsMulticast
())
666
{
667
SocketIpTtlTag
tag;
668
tag.
SetTtl
(
m_ipTtl
);
669
p->
AddPacketTag
(tag);
670
}
671
// There is no analgous to an IPv4 broadcast address in IPv6.
672
// Instead, we use a set of link-local, site-local, and global
673
// multicast addresses. The Ipv6 routing layers should all
674
// provide an interface-specific route to these addresses such
675
// that we can treat these multicast addresses as "not broadcast"
676
677
if
(
m_endPoint6
->
GetLocalAddress
() !=
Ipv6Address::GetAny
())
678
{
679
m_udp
->
Send
(p->
Copy
(),
m_endPoint6
->
GetLocalAddress
(), dest,
680
m_endPoint6
->
GetLocalPort
(),
port
, 0);
681
NotifyDataSent
(p->
GetSize
());
682
NotifySend
(
GetTxAvailable
());
683
return
p->
GetSize
();
684
}
685
else
if
(ipv6->
GetRoutingProtocol
() != 0)
686
{
687
Ipv6Header
header;
688
header.
SetDestinationAddress
(dest);
689
header.
SetNextHeader
(
UdpL4Protocol::PROT_NUMBER
);
690
Socket::SocketErrno
errno_;
691
Ptr<Ipv6Route>
route;
692
Ptr<NetDevice>
oif =
m_boundnetdevice
;
//specify non-zero if bound to a specific device
693
// TBD-- we could cache the route and just check its validity
694
route = ipv6->
GetRoutingProtocol
()->
RouteOutput
(p, header, oif, errno_);
695
if
(route != 0)
696
{
697
NS_LOG_LOGIC
(
"Route exists"
);
698
header.
SetSourceAddress
(route->GetSource ());
699
m_udp
->
Send
(p->
Copy
(), header.
GetSourceAddress
(), header.
GetDestinationAddress
(),
700
m_endPoint6
->
GetLocalPort
(),
port
, route);
701
NotifyDataSent
(p->
GetSize
());
702
return
p->
GetSize
();
703
}
704
else
705
{
706
NS_LOG_LOGIC
(
"No route to destination"
);
707
NS_LOG_ERROR
(errno_);
708
m_errno
= errno_;
709
return
-1;
710
}
711
}
712
else
713
{
714
NS_LOG_ERROR
(
"ERROR_NOROUTETOHOST"
);
715
m_errno
=
ERROR_NOROUTETOHOST
;
716
return
-1;
717
}
718
719
return
0;
720
}
721
722
// XXX maximum message size for UDP broadcast is limited by MTU
723
// size of underlying link; we are not checking that now.
724
uint32_t
725
UdpSocketImpl::GetTxAvailable
(
void
)
const
726
{
727
NS_LOG_FUNCTION_NOARGS
();
728
// No finite send buffer is modelled, but we must respect
729
// the maximum size of an IP datagram (65535 bytes - headers).
730
return
MAX_IPV4_UDP_DATAGRAM_SIZE
;
731
}
732
733
int
734
UdpSocketImpl::SendTo
(
Ptr<Packet>
p, uint32_t flags,
const
Address
&address)
735
{
736
NS_LOG_FUNCTION
(
this
<< p << flags << address);
737
if
(
InetSocketAddress::IsMatchingType
(address))
738
{
739
InetSocketAddress
transport =
InetSocketAddress::ConvertFrom
(address);
740
Ipv4Address
ipv4 = transport.
GetIpv4
();
741
uint16_t
port
= transport.
GetPort
();
742
return
DoSendTo
(p, ipv4, port);
743
}
744
else
if
(
Inet6SocketAddress::IsMatchingType
(address))
745
{
746
Inet6SocketAddress
transport =
Inet6SocketAddress::ConvertFrom
(address);
747
Ipv6Address
ipv6 = transport.
GetIpv6
();
748
uint16_t
port
= transport.
GetPort
();
749
return
DoSendTo
(p, ipv6, port);
750
}
751
return
-1;
752
}
753
754
uint32_t
755
UdpSocketImpl::GetRxAvailable
(
void
)
const
756
{
757
NS_LOG_FUNCTION_NOARGS
();
758
// We separately maintain this state to avoid walking the queue
759
// every time this might be called
760
return
m_rxAvailable
;
761
}
762
763
Ptr<Packet>
764
UdpSocketImpl::Recv
(uint32_t maxSize, uint32_t flags)
765
{
766
NS_LOG_FUNCTION
(
this
<< maxSize << flags);
767
if
(
m_deliveryQueue
.empty () )
768
{
769
m_errno
=
ERROR_AGAIN
;
770
return
0;
771
}
772
Ptr<Packet>
p =
m_deliveryQueue
.front ();
773
if
(p->
GetSize
() <= maxSize)
774
{
775
m_deliveryQueue
.pop ();
776
m_rxAvailable
-= p->
GetSize
();
777
}
778
else
779
{
780
p = 0;
781
}
782
return
p;
783
}
784
785
Ptr<Packet>
786
UdpSocketImpl::RecvFrom
(uint32_t maxSize, uint32_t flags,
787
Address
&fromAddress)
788
{
789
NS_LOG_FUNCTION
(
this
<< maxSize << flags);
790
Ptr<Packet>
packet =
Recv
(maxSize, flags);
791
if
(packet != 0)
792
{
793
SocketAddressTag
tag;
794
bool
found;
795
found = packet->
PeekPacketTag
(tag);
796
NS_ASSERT
(found);
797
fromAddress = tag.
GetAddress
();
798
}
799
return
packet;
800
}
801
802
int
803
UdpSocketImpl::GetSockName
(
Address
&address)
const
804
{
805
NS_LOG_FUNCTION_NOARGS
();
806
if
(
m_endPoint
!= 0)
807
{
808
address =
InetSocketAddress
(
m_endPoint
->
GetLocalAddress
(),
m_endPoint
->
GetLocalPort
());
809
}
810
else
811
{
812
// It is possible to call this method on a socket without a name
813
// in which case, behavior is unspecified
814
address =
InetSocketAddress
(
Ipv4Address::GetZero
(), 0);
815
}
816
return
0;
817
}
818
819
int
820
UdpSocketImpl::MulticastJoinGroup
(uint32_t interface,
const
Address
&groupAddress)
821
{
822
NS_LOG_FUNCTION
(interface << groupAddress);
823
/*
824
1) sanity check interface
825
2) sanity check that it has not been called yet on this interface/group
826
3) determine address family of groupAddress
827
4) locally store a list of (interface, groupAddress)
828
5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
829
*/
830
return
0;
831
}
832
833
int
834
UdpSocketImpl::MulticastLeaveGroup
(uint32_t interface,
const
Address
&groupAddress)
835
{
836
NS_LOG_FUNCTION
(interface << groupAddress);
837
/*
838
1) sanity check interface
839
2) determine address family of groupAddress
840
3) delete from local list of (interface, groupAddress); raise a LOG_WARN
841
if not already present (but return 0)
842
5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
843
*/
844
return
0;
845
}
846
847
void
848
UdpSocketImpl::BindToNetDevice
(
Ptr<NetDevice>
netdevice)
849
{
850
NS_LOG_FUNCTION
(netdevice);
851
Socket::BindToNetDevice
(netdevice);
// Includes sanity check
852
if
(
m_endPoint
== 0)
853
{
854
if
(
Bind
() == -1)
855
{
856
NS_ASSERT
(
m_endPoint
== 0);
857
return
;
858
}
859
NS_ASSERT
(
m_endPoint
!= 0);
860
}
861
m_endPoint
->
BindToNetDevice
(netdevice);
862
return
;
863
}
864
865
void
866
UdpSocketImpl::ForwardUp
(
Ptr<Packet>
packet,
Ipv4Header
header, uint16_t
port
,
867
Ptr<Ipv4Interface>
incomingInterface)
868
{
869
NS_LOG_FUNCTION
(
this
<< packet << header << port);
870
871
if
(
m_shutdownRecv
)
872
{
873
return
;
874
}
875
876
// Should check via getsockopt ()..
877
if
(
IsRecvPktInfo
())
878
{
879
Ipv4PacketInfoTag
tag;
880
packet->
RemovePacketTag
(tag);
881
tag.
SetRecvIf
(incomingInterface->
GetDevice
()->
GetIfIndex
());
882
packet->
AddPacketTag
(tag);
883
}
884
885
if
((
m_rxAvailable
+ packet->
GetSize
()) <=
m_rcvBufSize
)
886
{
887
Address
address =
InetSocketAddress
(header.
GetSource
(),
port
);
888
SocketAddressTag
tag;
889
tag.
SetAddress
(address);
890
packet->
AddPacketTag
(tag);
891
m_deliveryQueue
.push (packet);
892
m_rxAvailable
+= packet->
GetSize
();
893
NotifyDataRecv
();
894
}
895
else
896
{
897
// In general, this case should not occur unless the
898
// receiving application reads data from this socket slowly
899
// in comparison to the arrival rate
900
//
901
// drop and trace packet
902
NS_LOG_WARN
(
"No receive buffer space available. Drop."
);
903
m_dropTrace
(packet);
904
}
905
}
906
907
void
908
UdpSocketImpl::ForwardUp6
(
Ptr<Packet>
packet,
Ipv6Address
saddr,
Ipv6Address
daddr, uint16_t
port
)
909
{
910
NS_LOG_FUNCTION
(
this
<< packet << saddr << port);
911
912
if
(
m_shutdownRecv
)
913
{
914
return
;
915
}
916
917
if
((
m_rxAvailable
+ packet->
GetSize
()) <=
m_rcvBufSize
)
918
{
919
Address
address =
Inet6SocketAddress
(saddr, port);
920
SocketAddressTag
tag;
921
tag.
SetAddress
(address);
922
packet->
AddPacketTag
(tag);
923
m_deliveryQueue
.push (packet);
924
m_rxAvailable
+= packet->
GetSize
();
925
NotifyDataRecv
();
926
}
927
else
928
{
929
// In general, this case should not occur unless the
930
// receiving application reads data from this socket slowly
931
// in comparison to the arrival rate
932
//
933
// drop and trace packet
934
NS_LOG_WARN
(
"No receive buffer space available. Drop."
);
935
m_dropTrace
(packet);
936
}
937
}
938
939
void
940
UdpSocketImpl::ForwardIcmp
(
Ipv4Address
icmpSource, uint8_t icmpTtl,
941
uint8_t icmpType, uint8_t icmpCode,
942
uint32_t icmpInfo)
943
{
944
NS_LOG_FUNCTION
(
this
<< icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
945
(uint32_t)icmpCode << icmpInfo);
946
if
(!
m_icmpCallback
.
IsNull
())
947
{
948
m_icmpCallback
(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
949
}
950
}
951
952
void
953
UdpSocketImpl::ForwardIcmp6
(
Ipv6Address
icmpSource, uint8_t icmpTtl,
954
uint8_t icmpType, uint8_t icmpCode,
955
uint32_t icmpInfo)
956
{
957
NS_LOG_FUNCTION
(
this
<< icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
958
(uint32_t)icmpCode << icmpInfo);
959
if
(!
m_icmpCallback6
.
IsNull
())
960
{
961
m_icmpCallback6
(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
962
}
963
}
964
965
966
void
967
UdpSocketImpl::SetRcvBufSize
(uint32_t size)
968
{
969
m_rcvBufSize
= size;
970
}
971
972
uint32_t
973
UdpSocketImpl::GetRcvBufSize
(
void
)
const
974
{
975
return
m_rcvBufSize
;
976
}
977
978
void
979
UdpSocketImpl::SetIpTtl
(uint8_t ipTtl)
980
{
981
m_ipTtl
= ipTtl;
982
}
983
984
uint8_t
985
UdpSocketImpl::GetIpTtl
(
void
)
const
986
{
987
return
m_ipTtl
;
988
}
989
990
void
991
UdpSocketImpl::SetIpMulticastTtl
(uint8_t ipTtl)
992
{
993
m_ipMulticastTtl
= ipTtl;
994
}
995
996
uint8_t
997
UdpSocketImpl::GetIpMulticastTtl
(
void
)
const
998
{
999
return
m_ipMulticastTtl
;
1000
}
1001
1002
void
1003
UdpSocketImpl::SetIpMulticastIf
(int32_t ipIf)
1004
{
1005
m_ipMulticastIf
= ipIf;
1006
}
1007
1008
int32_t
1009
UdpSocketImpl::GetIpMulticastIf
(
void
)
const
1010
{
1011
return
m_ipMulticastIf
;
1012
}
1013
1014
void
1015
UdpSocketImpl::SetIpMulticastLoop
(
bool
loop)
1016
{
1017
m_ipMulticastLoop
= loop;
1018
}
1019
1020
bool
1021
UdpSocketImpl::GetIpMulticastLoop
(
void
)
const
1022
{
1023
return
m_ipMulticastLoop
;
1024
}
1025
1026
void
1027
UdpSocketImpl::SetMtuDiscover
(
bool
discover)
1028
{
1029
m_mtuDiscover
= discover;
1030
}
1031
bool
1032
UdpSocketImpl::GetMtuDiscover
(
void
)
const
1033
{
1034
return
m_mtuDiscover
;
1035
}
1036
1037
bool
1038
UdpSocketImpl::SetAllowBroadcast
(
bool
allowBroadcast)
1039
{
1040
m_allowBroadcast
= allowBroadcast;
1041
return
true
;
1042
}
1043
1044
bool
1045
UdpSocketImpl::GetAllowBroadcast
()
const
1046
{
1047
return
m_allowBroadcast
;
1048
}
1049
1050
1051
}
// namespace ns3
src
internet
model
udp-socket-impl.cc
Generated on Tue Oct 9 2012 16:45:39 for ns-3 by
1.8.1.2