Feature #8075 ยป socket.interface.patch
ext/socket/extconf.rb (working copy) | ||
---|---|---|
have_func("getpeerucred", headers)
|
||
have_func("if_indextoname", headers)
|
||
have_func("if_nametoindex", headers)
|
||
have_func("hsterror", headers)
|
||
have_func("getipnodebyname", headers)
|
||
... | ... | |
"udpsocket.#{$OBJEXT}",
|
||
"unixsocket.#{$OBJEXT}",
|
||
"unixserver.#{$OBJEXT}",
|
||
"interface.#{$OBJEXT}",
|
||
"option.#{$OBJEXT}",
|
||
"ancdata.#{$OBJEXT}",
|
||
"raddrinfo.#{$OBJEXT}"
|
ext/socket/init.c (working copy) | ||
---|---|---|
rsock_init_udpsocket();
|
||
rsock_init_unixsocket();
|
||
rsock_init_unixserver();
|
||
rsock_init_sockif();
|
||
rsock_init_sockopt();
|
||
rsock_init_ancdata();
|
||
rsock_init_addrinfo();
|
ext/socket/interface.c (working copy) | ||
---|---|---|
#include "rubysocket.h"
|
||
VALUE rb_cSockIf;
|
||
static ID id_name, id_index;
|
||
/* call-seq:
|
||
* Socket::Interface.list => array
|
||
*
|
||
* Returns an array of all interfaces.
|
||
*/
|
||
static VALUE
|
||
sockif_s_list(VALUE self)
|
||
{
|
||
struct if_nameindex *inp = NULL;
|
||
VALUE list, index;
|
||
inp = if_nameindex();
|
||
if (NULL == inp)
|
||
rb_sys_fail("if_nameindex(3)");
|
||
list = rb_ary_new();
|
||
for (off_t i = 0; inp[i].if_index; i++) {
|
||
index = UINT2NUM(inp[i].if_index);
|
||
rb_ary_push(list, rb_class_new_instance(1, &index, self));
|
||
}
|
||
if_freenameindex(inp);
|
||
return list;
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* Socket::Interface.new(name) => sockif
|
||
* Socket::Interface.new(index) => sockif
|
||
*
|
||
* Returns a new Socket::Interface object.
|
||
*/
|
||
static VALUE
|
||
sockif_initialize(VALUE self, VALUE interface)
|
||
{
|
||
unsigned int index;
|
||
char name[IFNAMSIZ];
|
||
if (FIXNUM_P(interface)) {
|
||
if (if_indextoname(FIX2UINT(interface), name) == NULL)
|
||
rb_sys_fail("if_indextoname(3)");
|
||
rb_ivar_set(self, id_index, interface);
|
||
rb_ivar_set(self, id_name, rb_str_new_cstr(name));
|
||
} else {
|
||
interface = rb_String(interface);
|
||
index = if_nametoindex(StringValueCStr(interface));
|
||
if (index == 0)
|
||
rb_sys_fail("if_nametoindex(3)");
|
||
rb_ivar_set(self, id_index, UINT2NUM(index));
|
||
rb_ivar_set(self, id_name, rb_String(interface));
|
||
}
|
||
return self;
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* sockif == other => true or false
|
||
*
|
||
* Compares this interface with +other+.
|
||
*/
|
||
static VALUE
|
||
sockif_eq(VALUE self, VALUE other)
|
||
{
|
||
VALUE index1, index2;
|
||
if (!rb_obj_is_kind_of(other, rb_cSockIf))
|
||
return Qfalse;
|
||
index1 = rb_attr_get(self, id_index);
|
||
index2 = rb_attr_get(other, id_index);
|
||
return index1 == index2 ? Qtrue : Qfalse;
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* sockif.index => Integer
|
||
*
|
||
* Returns the interface index as an Integer
|
||
*
|
||
* p Socket::Interface.new("lo0").index
|
||
* #=> 0
|
||
*/
|
||
static VALUE
|
||
sockif_index(VALUE self)
|
||
{
|
||
return rb_attr_get(self, id_index);
|
||
}
|
||
static VALUE
|
||
sockif_inspect(VALUE self)
|
||
{
|
||
VALUE _name = rb_attr_get(self, id_name);
|
||
unsigned int index = NUM2UINT(rb_attr_get(self, id_index));
|
||
char * name = StringValueCStr(_name);
|
||
return rb_sprintf("#<%s %s (index %d)>",
|
||
rb_obj_classname(self), name, index);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* sockif.name => String
|
||
*
|
||
* Returns the interface name as a String.
|
||
*
|
||
* p Socket::Interface.new(0).name
|
||
* #=> "lo0"
|
||
*/
|
||
static VALUE
|
||
sockif_name(VALUE self)
|
||
{
|
||
return rb_attr_get(self, id_name);
|
||
}
|
||
void
|
||
rsock_init_sockif(void)
|
||
{
|
||
id_name = rb_intern("name");
|
||
id_index = rb_intern("index");
|
||
/*
|
||
* Document-class: Socket::Interface
|
||
*
|
||
* Socket::Interface represents an interface packets may be sent or
|
||
* received on.
|
||
*/
|
||
rb_cSockIf = rb_define_class_under(rb_cSocket, "Interface", rb_cObject);
|
||
rb_define_singleton_method(rb_cSockIf, "list", sockif_s_list, 0);
|
||
rb_define_method(rb_cSockIf, "initialize", sockif_initialize, 1);
|
||
rb_define_method(rb_cSockIf, "==", sockif_eq, 1);
|
||
rb_define_method(rb_cSockIf, "name", sockif_name, 0);
|
||
rb_define_method(rb_cSockIf, "index", sockif_index, 0);
|
||
rb_define_method(rb_cSockIf, "inspect", sockif_inspect, 0);
|
||
}
|
||
ext/socket/rubysocket.h (working copy) | ||
---|---|---|
void rsock_init_socket_constants(void);
|
||
void rsock_init_ancdata(void);
|
||
void rsock_init_addrinfo(void);
|
||
void rsock_init_sockif(void);
|
||
void rsock_init_sockopt(void);
|
||
void rsock_init_socket_init(void);
|
||
test/socket/test_interface.rb (working copy) | ||
---|---|---|
require 'test/unit'
|
||
require 'socket'
|
||
class TestSocketInterface < Test::Unit::TestCase
|
||
def test_self_list
|
||
list = Socket::Interface.list
|
||
refute_empty list
|
||
assert list.all? { |iface| Socket::Interface === iface }
|
||
end
|
||
def test_initialize_index
|
||
assert_raises Errno::ENXIO do
|
||
Socket::Interface.new(0)
|
||
end
|
||
iface = Socket::Interface.new(1)
|
||
assert_instance_of Socket::Interface, iface
|
||
assert_equal 1, iface.index
|
||
end
|
||
def test_initialize_name
|
||
assert_raises Errno::ENXIO do
|
||
Socket::Interface.new('garbage name')
|
||
end
|
||
name = Socket::Interface.new(1).name
|
||
iface = Socket::Interface.new(name)
|
||
assert_instance_of Socket::Interface, iface
|
||
assert_equal name, iface.name
|
||
end
|
||
def test_equals2
|
||
iface1a = Socket::Interface.new(1)
|
||
iface1b = Socket::Interface.new(1)
|
||
iface2 = Socket::Interface.new(2)
|
||
assert_equal iface1a, iface1b
|
||
refute_equal iface1a, iface2
|
||
end
|
||
def test_index
|
||
iface = Socket::Interface.new(1)
|
||
assert_equal 1, iface.index
|
||
end
|
||
def test_inspect
|
||
iface = Socket::Interface.new(1)
|
||
assert_equal "#<Socket::Interface #{iface.name} (index #{iface.index})>",
|
||
iface.inspect
|
||
end
|
||
def test_name
|
||
iface = Socket::Interface.new(1)
|
||
name = iface.name
|
||
assert_kind_of String, name
|
||
refute_empty name
|
||
end
|
||
end
|
||