Project

General

Profile

Feature #8075 ยป socket.interface.patch

drbrain (Eric Hodel), 03/11/2013 12:20 PM

View differences:

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
    (1-1/1)