socket.interface.patch

Eric Hodel, 03/11/2013 12:20 PM

Download (6.55 KB)

View differences:

ext/socket/extconf.rb (working copy)
118 118
  have_func("getpeerucred", headers)
119 119

  
120 120
  have_func("if_indextoname", headers)
121
  have_func("if_nametoindex", headers)
121 122

  
122 123
  have_func("hsterror", headers)
123 124
  have_func("getipnodebyname", headers)
......
463 464
    "udpsocket.#{$OBJEXT}",
464 465
    "unixsocket.#{$OBJEXT}",
465 466
    "unixserver.#{$OBJEXT}",
467
    "interface.#{$OBJEXT}",
466 468
    "option.#{$OBJEXT}",
467 469
    "ancdata.#{$OBJEXT}",
468 470
    "raddrinfo.#{$OBJEXT}"
ext/socket/init.c (working copy)
620 620
    rsock_init_udpsocket();
621 621
    rsock_init_unixsocket();
622 622
    rsock_init_unixserver();
623
    rsock_init_sockif();
623 624
    rsock_init_sockopt();
624 625
    rsock_init_ancdata();
625 626
    rsock_init_addrinfo();
ext/socket/interface.c (working copy)
1
#include "rubysocket.h"
2

  
3
VALUE rb_cSockIf;
4

  
5
static ID id_name, id_index;
6

  
7
/* call-seq:
8
 *   Socket::Interface.list => array
9
 *
10
 * Returns an array of all interfaces.
11
 */
12
static VALUE
13
sockif_s_list(VALUE self)
14
{
15
    struct if_nameindex *inp = NULL;
16
    VALUE list, index;
17

  
18
    inp = if_nameindex();
19

  
20
    if (NULL == inp)
21
	rb_sys_fail("if_nameindex(3)");
22

  
23
    list = rb_ary_new();
24

  
25
    for (off_t i = 0; inp[i].if_index; i++) {
26
	index = UINT2NUM(inp[i].if_index);
27
	rb_ary_push(list, rb_class_new_instance(1, &index, self));
28
    }
29

  
30
    if_freenameindex(inp);
31

  
32
    return list;
33
}
34

  
35
/*
36
 * call-seq:
37
 *   Socket::Interface.new(name)  => sockif
38
 *   Socket::Interface.new(index) => sockif
39
 *
40
 * Returns a new Socket::Interface object.
41
 */
42

  
43
static VALUE
44
sockif_initialize(VALUE self, VALUE interface)
45
{
46
    unsigned int index;
47
    char name[IFNAMSIZ];
48

  
49
    if (FIXNUM_P(interface)) {
50
	if (if_indextoname(FIX2UINT(interface), name) == NULL)
51
	    rb_sys_fail("if_indextoname(3)");
52

  
53
	rb_ivar_set(self, id_index, interface);
54
	rb_ivar_set(self, id_name,  rb_str_new_cstr(name));
55
    } else {
56
	interface = rb_String(interface);
57

  
58
	index = if_nametoindex(StringValueCStr(interface));
59

  
60
	if (index == 0)
61
	    rb_sys_fail("if_nametoindex(3)");
62

  
63
	rb_ivar_set(self, id_index, UINT2NUM(index));
64
	rb_ivar_set(self, id_name, rb_String(interface));
65
    }
66

  
67
    return self;
68
}
69

  
70
/*
71
 * call-seq:
72
 *   sockif == other => true or false
73
 *
74
 * Compares this interface with +other+.
75
 */
76
static VALUE
77
sockif_eq(VALUE self, VALUE other)
78
{
79
    VALUE index1, index2;
80

  
81
    if (!rb_obj_is_kind_of(other, rb_cSockIf))
82
	return Qfalse;
83

  
84
    index1 = rb_attr_get(self,  id_index);
85
    index2 = rb_attr_get(other, id_index);
86

  
87
    return  index1 == index2 ? Qtrue : Qfalse;
88
}
89

  
90
/*
91
 * call-seq:
92
 *   sockif.index => Integer
93
 *
94
 * Returns the interface index as an Integer
95
 *
96
 *   p Socket::Interface.new("lo0").index
97
 *   #=> 0
98
 */
99
static VALUE
100
sockif_index(VALUE self)
101
{
102
    return rb_attr_get(self, id_index);
103
}
104

  
105
static VALUE
106
sockif_inspect(VALUE self)
107
{
108
    VALUE _name = rb_attr_get(self, id_name);
109
    unsigned int index = NUM2UINT(rb_attr_get(self, id_index));
110
    char * name = StringValueCStr(_name);
111

  
112
    return rb_sprintf("#<%s %s (index %d)>",
113
	    rb_obj_classname(self), name, index);
114
}
115

  
116
/*
117
 * call-seq:
118
 *   sockif.name => String
119
 *
120
 * Returns the interface name as a String.
121
 *
122
 *   p Socket::Interface.new(0).name
123
 *   #=> "lo0"
124
 */
125
static VALUE
126
sockif_name(VALUE self)
127
{
128
    return rb_attr_get(self, id_name);
129
}
130

  
131
void
132
rsock_init_sockif(void)
133
{
134
    id_name  = rb_intern("name");
135
    id_index = rb_intern("index");
136

  
137
    /*
138
     * Document-class: Socket::Interface
139
     *
140
     * Socket::Interface represents an interface packets may be sent or
141
     * received on.
142
     */
143
    rb_cSockIf = rb_define_class_under(rb_cSocket, "Interface", rb_cObject);
144

  
145
    rb_define_singleton_method(rb_cSockIf, "list", sockif_s_list, 0);
146

  
147
    rb_define_method(rb_cSockIf, "initialize", sockif_initialize, 1);
148

  
149
    rb_define_method(rb_cSockIf, "==",      sockif_eq,      1);
150
    rb_define_method(rb_cSockIf, "name",    sockif_name,    0);
151
    rb_define_method(rb_cSockIf, "index",   sockif_index,   0);
152
    rb_define_method(rb_cSockIf, "inspect", sockif_inspect, 0);
153
}
154

  
ext/socket/rubysocket.h (working copy)
330 330
void rsock_init_socket_constants(void);
331 331
void rsock_init_ancdata(void);
332 332
void rsock_init_addrinfo(void);
333
void rsock_init_sockif(void);
333 334
void rsock_init_sockopt(void);
334 335
void rsock_init_socket_init(void);
335 336

  
test/socket/test_interface.rb (working copy)
1
require 'test/unit'
2
require 'socket'
3

  
4
class TestSocketInterface < Test::Unit::TestCase
5

  
6
  def test_self_list
7
    list = Socket::Interface.list
8

  
9
    refute_empty list
10

  
11
    assert list.all? { |iface| Socket::Interface === iface }
12
  end
13

  
14
  def test_initialize_index
15
    assert_raises Errno::ENXIO do
16
      Socket::Interface.new(0)
17
    end
18

  
19
    iface = Socket::Interface.new(1)
20

  
21
    assert_instance_of Socket::Interface, iface
22
    assert_equal 1, iface.index
23
  end
24

  
25
  def test_initialize_name
26
    assert_raises Errno::ENXIO do
27
      Socket::Interface.new('garbage name')
28
    end
29

  
30
    name = Socket::Interface.new(1).name
31
    iface = Socket::Interface.new(name)
32

  
33
    assert_instance_of Socket::Interface, iface
34
    assert_equal name, iface.name
35
  end
36

  
37
  def test_equals2
38
    iface1a = Socket::Interface.new(1)
39
    iface1b = Socket::Interface.new(1)
40
    iface2  = Socket::Interface.new(2)
41

  
42
    assert_equal iface1a, iface1b
43
    refute_equal iface1a, iface2
44
  end
45

  
46
  def test_index
47
    iface = Socket::Interface.new(1)
48

  
49
    assert_equal 1, iface.index
50
  end
51

  
52
  def test_inspect
53
    iface = Socket::Interface.new(1)
54

  
55
    assert_equal "#<Socket::Interface #{iface.name} (index #{iface.index})>",
56
                 iface.inspect
57
  end
58

  
59
  def test_name
60
    iface = Socket::Interface.new(1)
61

  
62
    name = iface.name
63

  
64
    assert_kind_of String, name
65
    refute_empty name
66
  end
67

  
68
end
69