From: Stephane D'Alu Date: 2003-04-25T08:29:12+09:00 Subject: Re: IPaddr design On Fri, Apr 25, 2003 at 03:43:11AM +0900, Hajimu UMEMOTO wrote: > Hi, > > Since I was not on the list, knu-san notified me of your mail. So, > I've just subscribed the list. thank you. > > >>>>> On Thu, 24 Apr 2003 19:34:14 +0200 > >>>>> "Stephane D'Alu" said: > > Stephane> - having sub classes IPv4, IPv6 (and IPv6::Compatible) instead > Stephane> of one class doing it all (fall better in the object oriented design) > > When I made ipaddr, I thought whether IPv4 and IPv6 should be > implemented as separate class or not. If IPv4 and IPv6 are separate > classes, a user of the classes has to care which address family is > using. I prefer address family independent programing which means we > don't care address family as possible. So, I decide to implement it > as one class. > I totaly agree that the user in the general case shouldn't need to choose between IPv4 or IPv6 (or even think about it), but I would still like, as a programmer when doing "low network operations" be able to know what kind of addresses are manipulated without asking (ipv4? or ipv6? or ...) I think we can manage to please both, the standard application programmer and the picky network programmer, at the same time. This would only require to have - Address being a kind of abstract class, so that IPv4 or IPv6 addresses have the same common behaviour inside an application - a class method in Address being able to return an object not of type Address but IPv4 or IPv6 I'm taking some part of my code as an illustration: class Address class IPv4 < Address def create(..) end end class IPv6 < Address def create(..) end end OrderDefault = [ Address::IPv4, Address::IPv6 ] def self.create(arg, order=OrderDefault) order.each { |klass| begin return klass::create(arg) rescue InvalidAddress end } raise InvalidAddress, "can't interpret #{arg.inspect} as address" end end With this approch we still give the possibility to the people who want to use/implement IPv8, to do it easily ;-> So the network progammer who requires fine control can do: a = Address::IPv4::create("127.0.0.1") b = Address::IPv6::create("::1") case a when Address::IPv4 when Address::IPv6 end The application progammer who doesn't care do: a = Address::create("127.0.0.1") b = Address::create("::1") > Stephane> - when creating an address from a string, being able to select > Stephane> how the string should be interpreted (ipv4 or ipv4 mapped) > Stephane> (OrderStrict, OrderCompatibility, OrderIPv6Only, OrderIPv4Only) > Stephane> This will give finer control on the type of addresses that > Stephane> should be created (and could allow to easily swap to IPv6 only > Stephane> or remover IPv4 mapped addresses (there are already some talk about it)) > > It's a good idea. Someone may want to traet an address strictly. or in a year or two consider IPv6 as the default (ok, I'm optimistic ;) > > Stephane> - keeping some regular expression to test if a string match an ip address > Stephane> (IPv6StrictRegex, IPv6Regex, IPv6LooseRegex, ...) > > How do you use these regular expressions? I think it can be tested by > whether a string can be converted to an address or not. This would be use (as it was in resolv.rb) by doing: case string_addr when IPv6StrictRegex # match IPv6 format only when IPv6LooseRegex # match IPv6 and IPv4 (as it can be considerer as mapped) end So by saying that it can be tested by converting it, I assume that some method using C code are called to do the job. Now would it still be possible to create IPv6 addresses from string if the system on which you are compiling ruby doesn't have support for IPv6. I know this can seem a strange request, but you can want to manipulate different addresss type even if they are not all supported on your system (I'm in this case) > > Stephane> - having some commonly used constant defined (Loopback) > > It's good idea having constant. However, once we decide to have some > constants, we need more constants than only Loopback. This is why I > didn't add constants, yet. ok, so lets see, we can also add 'Wildcard' IPv4::Wildcard = '0.0.0.0' IPv6::Wildcard = '::' this makes 2 ;) and for more specific address type: IPv4 : broadcast = '255.255.255.255' IPv6 : link local all nodes = 'FF02::1' link local all routers = 'FF02::2' > > Stephane> - the method name 'reverse' for ipaddr seems confusing when compared > Stephane> to class string or array > > Yup, I think so. Do you have any idea about the name? > could be perhaps 'to_name' or 'to_dnsname' (or 'to_arpa' if we assume that .ip6.int is deprecated as it should be, but I would prefer avoiding this name) > Stephane> - scope_id or prefixlen are not directly part of an ip address > Stephane> and so should not be included in the class, if someone want/need > Stephane> them a new class should be created, this could be in the > Stephane> case of scope_id a class called SockAddr. > > I implemented ipaddr as you say at the begining. But, it was somewhat > diffuse. So, I merged these into one class. > > Stephane> - the | or & operator has some usefullness when dealing with netmask, > Stephane> but netmask and IPv4 classes (A, B, C, ..) have been depretiated in > Stephane> favor of prefixlen. now for the operators '<<' '>>' and '~', I should > Stephane> say that I have difficulties to find a real use for them. > > > It is useful when getting some part of the address or makeing IP > address. Especially, IPv6 address is structured. this give the false feeling that the concept of netmask is still in use, or that you can do bit operations over IP addresses c = a & b will only give a usefull address c in a very precise condition (and the shift operator seems even more hazardous) Such low operations for IP address construction can already easily be done in your code by: c = IPAddr::new(a.to_i & b.to_i) As it can be done, I guess network programmers won't mind this little extra step, and if they do it is easy in ruby to add new methods to an already loaded class. As a way of structuring IPv6, I would rather prefer a dedicated IPv6 class where the following methods are available: - eui64 - prefix(len=64) - create_from_eui64 - create_from_mac - in_net?(prefix, len=64) - link_local? - site_local? - anycast? - is_mapped? - is_compatible? To implement all this method, I agree we will need the &, |, << .., but it will be possible to do it directly on @addr It would also be nice, that we ensure that IP addresses are immutable objects. So in case you're wondering why I'm such annoying about IP addresses (DNS will come later :), this is for this kind of application: http://zonecheck.nic.fr/v2/ I would like to keep ruby libraries easy to use when in the general case, but still powerful enough (or at least not removing the possibility to make it powerful by overloading classes) when there is a need of a low level access. Sincerly -- Stephane D'Alu