1use prelude::{SocketOption, GetSocketOption, SetSocketOption};
2use ffi::*;
3use ip::{IpProtocol, IpAddrV4, IpAddrV6, IpAddr, Tcp};
4
5use std::mem;
6
7fn in_addr_of(addr: IpAddrV4) -> in_addr {
8 unsafe { mem::transmute(addr) }
9}
10
11fn in6_addr_of(addr: IpAddrV6) -> in6_addr {
12 unsafe { mem::transmute_copy(addr.as_bytes()) }
13}
14
15#[derive(Default, Clone)]
45pub struct V6Only(i32);
46
47impl V6Only {
48 pub fn new(on: bool) -> V6Only {
49 V6Only(on as i32)
50 }
51
52 pub fn get(&self) -> bool {
53 self.0 != 0
54 }
55
56 pub fn set(&mut self, on: bool) {
57 self.0 = on as i32
58 }
59}
60
61impl<P: IpProtocol> SocketOption<P> for V6Only {
62 type Data = i32;
63
64 fn level(&self, _: &P) -> i32 {
65 IPPROTO_IPV6.i32()
66 }
67
68 fn name(&self, _: &P) -> i32 {
69 IPV6_V6ONLY
70 }
71
72}
73
74impl<P: IpProtocol> GetSocketOption<P> for V6Only {
75 fn data_mut(&mut self) -> &mut Self::Data {
76 &mut self.0
77 }
78}
79
80impl<P: IpProtocol> SetSocketOption<P> for V6Only {
81 fn data(&self) -> &Self::Data {
82 &self.0
83 }
84}
85
86#[derive(Default, Clone)]
116pub struct NoDelay(i32);
117
118impl NoDelay {
119 pub fn new(on: bool) -> NoDelay {
120 NoDelay(on as i32)
121 }
122
123 pub fn get(&self) -> bool {
124 self.0 != 0
125 }
126
127 pub fn set(&mut self, on: bool) {
128 self.0 = on as i32
129 }
130}
131
132impl SocketOption<Tcp> for NoDelay {
133 type Data = i32;
134
135 fn level(&self, _: &Tcp) -> i32 {
136 IPPROTO_TCP.i32()
137 }
138
139 fn name(&self, _: &Tcp) -> i32 {
140 TCP_NODELAY
141 }
142}
143
144impl GetSocketOption<Tcp> for NoDelay {
145 fn data_mut(&mut self) -> &mut Self::Data {
146 &mut self.0
147 }
148}
149
150impl SetSocketOption<Tcp> for NoDelay {
151 fn data(&self) -> &Self::Data {
152 &self.0
153 }
154}
155
156#[derive(Default, Clone)]
186pub struct UnicastHops(i32);
187
188impl UnicastHops {
189 pub fn new(ttl: u8) -> UnicastHops {
190 UnicastHops(ttl as i32)
191 }
192
193 pub fn get(&self) -> u8 {
194 self.0 as u8
195 }
196
197 pub fn set(&mut self, ttl: u8) {
198 self.0 = ttl as i32
199 }
200}
201
202impl<P: IpProtocol> SocketOption<P> for UnicastHops {
203 type Data = i32;
204
205 fn level(&self, pro: &P) -> i32 {
206 if pro.is_v4() {
207 IPPROTO_IP.i32()
208 } else if pro.is_v6() {
209 IPPROTO_IPV6.i32()
210 } else {
211 unreachable!("Invalid ip version")
212 }
213 }
214
215 fn name(&self, pro: &P) -> i32 {
216 if pro.is_v4() {
217 IP_TTL
218 } else if pro.is_v6() {
219 IPV6_UNICAST_HOPS
220 } else {
221 unreachable!("Invalid ip version")
222 }
223 }
224}
225
226impl<P: IpProtocol> GetSocketOption<P> for UnicastHops {
227 fn data_mut(&mut self) -> &mut Self::Data {
228 &mut self.0
229 }
230}
231
232impl<P: IpProtocol> SetSocketOption<P> for UnicastHops {
233 fn data(&self) -> &Self::Data {
234 &self.0
235 }
236}
237
238#[derive(Default, Clone)]
268pub struct MulticastEnableLoopback(i32);
269
270impl MulticastEnableLoopback {
271 pub fn new(on: bool) -> MulticastEnableLoopback {
272 MulticastEnableLoopback(on as i32)
273 }
274
275 pub fn get(&self) -> bool {
276 self.0 != 0
277 }
278
279 pub fn set(&mut self, on: bool) {
280 self.0 = on as i32
281 }
282}
283
284impl<P: IpProtocol> SocketOption<P> for MulticastEnableLoopback {
285 type Data = i32;
286
287 fn level(&self, pro: &P) -> i32 {
288 if pro.is_v4() {
289 IPPROTO_IP.i32()
290 } else if pro.is_v6() {
291 IPPROTO_IPV6.i32()
292 } else {
293 unreachable!("Invalid ip version")
294 }
295 }
296
297 fn name(&self, pro: &P) -> i32 {
298 if pro.is_v4() {
299 IP_MULTICAST_LOOP
300 } else if pro.is_v6() {
301 IPV6_MULTICAST_LOOP
302 } else {
303 unreachable!("Invalid ip version")
304 }
305 }
306}
307
308impl<P: IpProtocol> GetSocketOption<P> for MulticastEnableLoopback {
309 fn data_mut(&mut self) -> &mut Self::Data {
310 &mut self.0
311 }
312}
313
314impl<P: IpProtocol> SetSocketOption<P> for MulticastEnableLoopback {
315 fn data(&self) -> &Self::Data {
316 &self.0
317 }
318}
319
320#[derive(Default, Clone)]
350pub struct MulticastHops(i32);
351
352impl MulticastHops {
353 pub fn new(ttl: u8) -> MulticastHops {
354 MulticastHops(ttl as i32)
355 }
356
357 pub fn get(&self) -> u8 {
358 self.0 as u8
359 }
360
361 pub fn set(&mut self, ttl: u8) {
362 self.0 = ttl as i32
363 }
364}
365
366impl<P: IpProtocol> SocketOption<P> for MulticastHops {
367 type Data = i32;
368
369 fn level(&self, pro: &P) -> i32 {
370 if pro.is_v4() {
371 IPPROTO_IP.i32()
372 } else if pro.is_v6() {
373 IPPROTO_IPV6.i32()
374 } else {
375 unreachable!("Invalid ip version")
376 }
377 }
378
379 fn name(&self, pro: &P) -> i32 {
380 if pro.is_v4() {
381 IP_MULTICAST_TTL
382 } else if pro.is_v6() {
383 IPV6_MULTICAST_HOPS
384 } else {
385 unreachable!("Invalid ip version")
386 }
387 }
388}
389
390impl<P: IpProtocol> GetSocketOption<P> for MulticastHops {
391 fn data_mut(&mut self) -> &mut Self::Data {
392 &mut self.0
393 }
394}
395
396impl<P: IpProtocol> SetSocketOption<P> for MulticastHops {
397 fn data(&self) -> &Self::Data {
398 &self.0
399 }
400}
401
402#[derive(Clone)]
403enum Mreq {
404 V4(ip_mreq),
405 V6(ipv6_mreq),
406}
407
408#[derive(Clone)]
425pub struct MulticastJoinGroup(Mreq);
426
427impl MulticastJoinGroup {
428 pub fn new(multicast: IpAddr) -> MulticastJoinGroup {
429 match multicast {
430 IpAddr::V4(multicast) => Self::from_v4(multicast, IpAddrV4::any()),
431 IpAddr::V6(multicast) => {
432 let scope_id = multicast.get_scope_id();
433 Self::from_v6(multicast, scope_id)
434 }
435 }
436 }
437
438 pub fn from_v4(multicast: IpAddrV4, interface: IpAddrV4) -> MulticastJoinGroup {
439 MulticastJoinGroup(Mreq::V4(ip_mreq {
440 imr_multiaddr: in_addr_of(multicast),
441 imr_interface: in_addr_of(interface),
442 }))
443 }
444
445 pub fn from_v6(multicast: IpAddrV6, scope_id: u32) -> MulticastJoinGroup {
446 MulticastJoinGroup(Mreq::V6(ipv6_mreq {
447 ipv6mr_multiaddr: in6_addr_of(multicast),
448 ipv6mr_interface: scope_id,
449 }))
450 }
451}
452
453impl<P: IpProtocol> SocketOption<P> for MulticastJoinGroup {
454 type Data = ();
455
456 fn level(&self, pro: &P) -> i32 {
457 if pro.is_v4() {
458 IPPROTO_IP.i32()
459 } else if pro.is_v6() {
460 IPPROTO_IPV6.i32()
461 } else {
462 unreachable!("Invalid ip version")
463 }
464 }
465
466 fn name(&self, pro: &P) -> i32 {
467 if pro.is_v4() {
468 IP_ADD_MEMBERSHIP
469 } else if pro.is_v6() {
470 IPV6_JOIN_GROUP
471 } else {
472 unreachable!("Invalid ip version")
473 }
474 }
475}
476
477impl<P: IpProtocol> SetSocketOption<P> for MulticastJoinGroup {
478 fn data(&self) -> &Self::Data {
479 match &self.0 {
480 &Mreq::V4(ref mreq) => unsafe { mem::transmute(mreq) },
481 &Mreq::V6(ref mreq) => unsafe { mem::transmute(mreq) },
482 }
483 }
484
485 fn size(&self) -> usize {
486 match &self.0 {
487 &Mreq::V4(ref mreq) => mem::size_of_val(mreq),
488 &Mreq::V6(ref mreq) => mem::size_of_val(mreq),
489 }
490 }
491}
492
493#[derive(Clone)]
510pub struct MulticastLeaveGroup(Mreq);
511
512impl MulticastLeaveGroup {
513 pub fn new(multicast: IpAddr) -> MulticastLeaveGroup {
514 match multicast {
515 IpAddr::V4(multicast) => Self::from_v4(multicast, IpAddrV4::any()),
516 IpAddr::V6(multicast) => {
517 let scope_id = multicast.get_scope_id();
518 Self::from_v6(multicast, scope_id)
519 }
520 }
521 }
522
523 pub fn from_v4(multicast: IpAddrV4, interface: IpAddrV4) -> MulticastLeaveGroup {
524 MulticastLeaveGroup(Mreq::V4(ip_mreq {
525 imr_multiaddr: in_addr_of(multicast),
526 imr_interface: in_addr_of(interface),
527 }))
528 }
529
530 pub fn from_v6(multicast: IpAddrV6, scope_id: u32) -> MulticastLeaveGroup {
531 MulticastLeaveGroup(Mreq::V6(ipv6_mreq {
532 ipv6mr_multiaddr: in6_addr_of(multicast),
533 ipv6mr_interface: scope_id,
534 }))
535 }
536}
537
538impl<P: IpProtocol> SocketOption<P> for MulticastLeaveGroup {
539 type Data = ();
540
541 fn level(&self, pro: &P) -> i32 {
542 if pro == &P::v4() {
543 IPPROTO_IP.i32()
544 } else if pro.is_v6() {
545 IPPROTO_IPV6.i32()
546 } else {
547 unreachable!("Invalid ip version")
548 }
549 }
550
551 fn name(&self, pro: &P) -> i32 {
552 if pro.is_v4() {
553 IP_DROP_MEMBERSHIP
554 } else if pro.is_v6() {
555 IPV6_LEAVE_GROUP
556 } else {
557 unreachable!("Invalid ip version")
558 }
559 }
560}
561
562impl<P: IpProtocol> SetSocketOption<P> for MulticastLeaveGroup {
563 fn data(&self) -> &Self::Data {
564 match &self.0 {
565 &Mreq::V4(ref mreq) => unsafe { mem::transmute(mreq) },
566 &Mreq::V6(ref mreq) => unsafe { mem::transmute(mreq) },
567 }
568 }
569
570 fn size(&self) -> usize {
571 match &self.0 {
572 &Mreq::V4(ref mreq) => mem::size_of_val(mreq),
573 &Mreq::V6(ref mreq) => mem::size_of_val(mreq),
574 }
575 }
576}
577
578#[derive(Clone)]
579enum Iface {
580 V4(in_addr),
581 V6(u32),
582}
583
584#[derive(Clone)]
601pub struct OutboundInterface(Iface);
602
603impl OutboundInterface {
604 pub fn new(interface: IpAddr) -> OutboundInterface {
605 match interface {
606 IpAddr::V4(interface) => Self::from_v4(interface),
607 IpAddr::V6(interface) => Self::from_v6(interface),
608 }
609 }
610
611 pub fn from_v4(interface: IpAddrV4) -> OutboundInterface {
612 OutboundInterface(Iface::V4(in_addr_of(interface)))
613 }
614
615 pub fn from_v6(interface: IpAddrV6) -> OutboundInterface {
616 OutboundInterface(Iface::V6(interface.get_scope_id()))
617 }
618}
619
620impl<P: IpProtocol> SocketOption<P> for OutboundInterface {
621 type Data = u32;
622
623 fn level(&self, pro: &P) -> i32 {
624 if pro.is_v4() {
625 IPPROTO_IP.i32()
626 } else if pro.is_v6() {
627 IPPROTO_IPV6.i32()
628 } else {
629 unreachable!("Invalid ip version")
630 }
631 }
632
633 fn name(&self, pro: &P) -> i32 {
634 if pro.is_v4() {
635 IP_MULTICAST_IF
636 } else if pro.is_v6() {
637 IPV6_MULTICAST_IF
638 } else {
639 unreachable!("Invalid ip version")
640 }
641 }
642}
643
644impl<P: IpProtocol> SetSocketOption<P> for OutboundInterface {
645 fn data(&self) -> &Self::Data {
646 match &self.0 {
647 &Iface::V4(ref addr) => unsafe { mem::transmute(addr) },
648 &Iface::V6(ref scope_id) => &scope_id,
649 }
650 }
651}
652
653#[test]
654fn test_outbound_interface() {
655 assert_eq!(mem::size_of::<u32>(), mem::size_of::<in_addr>());
656}