As I was posting on my Flex blog, I started to wonder if there's a design assumption going on that I hadn't considered.
I was thinking that Ruby could use a repository where individuals can share modules. Basically, a large collection of software and documentation.
Or do we?
Take Perl. Do you want to turn your Perl script into a CGI system? Go to CPAN -- the Comprehensive Perl Archive Network -- and grab the CGI module (okay, bad example, it's included in the standard distribution, but you get the idea). CPAN has bazillions of modules, and is an invaluable resource for handling whatever you need to handle. Proofs of concepts get hammered out, new ideas get born, and thoughtful robust code is freely available. All in one practical place.
But, perhaps Ruby has a higher level of focus. I see RubyForge: support for "projects", i.e. full applications, hinting that the modules there require just a bit too much cohesion to be generally useful. Instead of plug-in modules that you can use to add functionality to an application, does Ruby tend to focus on the applications (or projects) themselves?
Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts
Monday, May 11, 2009
Wednesday, April 22, 2009
def() and a module idea
Since I don't use Ruby for my job, this blog is in danger of dying a horrible but quick death.
I like def
...however, there is one thing I'd like to put on the record about Ruby. I like "def" to define methods, functions, subroutines, whatever you want to call them. Def has more currency than Perl's "sub". If Perl6 allowed "def" as a synonym for "sub" I'd be pleased.
Sound like a meaningless detail? The devil, I say, is in the details.
Something I don't think I like, on the other hand, is using "end" to close definitions (class...end. def...end.). True, it's obvious, and it's only one more keystroke than [shift+close bracket]. But, I seem to prefer keywords having more utility than as a block delimiter.
But that IS a reasonably trivial detail, one I can overlook.
A module idea
There's a science-fiction game called Traveller that's been in print for thirty years, and one of the key elements in the game is a world abstract, called the Universal World Profile, or UWP for short. It is self-contained with a handful of data elements, some fully derived data, some externally imposed data, and some computations you can perform. In short, perfect for a module. I think a good learning exercise is to port my Perl UWP module into Ruby.
I like def
...however, there is one thing I'd like to put on the record about Ruby. I like "def" to define methods, functions, subroutines, whatever you want to call them. Def has more currency than Perl's "sub". If Perl6 allowed "def" as a synonym for "sub" I'd be pleased.
Sound like a meaningless detail? The devil, I say, is in the details.
Something I don't think I like, on the other hand, is using "end" to close definitions (class...end. def...end.). True, it's obvious, and it's only one more keystroke than [shift+close bracket]. But, I seem to prefer keywords having more utility than as a block delimiter.
But that IS a reasonably trivial detail, one I can overlook.
A module idea
There's a science-fiction game called Traveller that's been in print for thirty years, and one of the key elements in the game is a world abstract, called the Universal World Profile, or UWP for short. It is self-contained with a handful of data elements, some fully derived data, some externally imposed data, and some computations you can perform. In short, perfect for a module. I think a good learning exercise is to port my Perl UWP module into Ruby.
Tuesday, March 24, 2009
TFTP Packet Factory
Straightforward, but fun.
class PacketFactory # TFTP = RFC 1350, 2347, 2348 (not needed here)
# #
# 2 bytes string 1b string 1b string 1b string 1b ... #
# +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+--> #
# | 01 |filename| 0 | mode | 0 | opt1 | 0 | value1 | 0 | < #
# +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+--> #
# string 1b string 1b #
# >-------+---+---~~---+---+ #
# < optN | 0 | valueN | 0 | #
# >-------+---+---~~---+---+ #
# #
# RRQ packet #
# #
# The mode field contains the string "netascii", "octet", or "mail" #
# #
def buildRRQ( filename, mode, *opts )
packet = "\0\1" + filename + "\0" + mode + "\0"
opts.each { |o| packet += o + "\0" }
return packet
end
# #
# 2 bytes string 1b string 1b string 1b string 1b ... #
# +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+--> #
# | 02 |filename| 0 | mode | 0 | opt1 | 0 | value1 | 0 | < #
# +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+--> #
# string 1b string 1b #
# >-------+---+---~~---+---+ #
# < optN | 0 | valueN | 0 | #
# >-------+---+---~~---+---+ #
# #
# WRQ packet #
# #
def buildWRQ( filename, mode, blocksize, octets )
packet = "\0\2" + filename + "\0"
+ mode + "\0"
+ blocksize + "\0"
+ octets + "\0"
return packet
end
# #
# 2 bytes 2 bytes n bytes #
# ---------------------------------- #
# | 03 | Block # | Data | #
# ---------------------------------- #
# #
# DATA packet #
# #
def buildDAT( blocknum, data )
return "\0\3" + [blocknum, data].flatten.pack("n*")
end
# #
# 2 bytes 2 bytes #
# --------------------- #
# | 04 | Block # | #
# --------------------- #
# #
# ACK packet #
# #
def buildACK( blocknum ) return "\0\4" + [blocknum].pack("n") end
def buildACKfromDAT( packet )
packet = packet[0..3]
packet[1] = "\04"
return packet
end
# #
# 2 bytes string 1b string 1b...string 1b string 1b #
# +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+ #
# | 06 | opt1 | 0 | value1 | 0 | optN | 0 | valueN | 0 | #
# +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+ #
# #
# OACK packet [RFC 2347] #
# #
def buildOACK( opt_hash )
packet = "\0\6"
opt_hash.each_pair { |k,v| packet += k + "\0" + v + "\0" }
return packet
end
# #
# 2 bytes 2 bytes string 1 byte #
# ----------------------------------------- #
# | 05 | ErrorCode | ErrMsg | 0 | #
# ----------------------------------------- #
# #
# ERROR packet #
# #
# Error Codes #
# #
# Value Meaning #
# #
# 0 Not defined, see error message (if any). #
# 1 File not found. #
# 2 Access violation. #
# 3 Disk full or allocation exceeded. #
# 4 Illegal TFTP operation. #
# 5 Unknown transfer ID. #
# 6 File already exists. #
# 7 No such user. #
# 8 Invalid option value requested. [RFC 2347] #
# #
def buildERR( errcode, errmsg )
packet = "\0\5" + [errcode, errmsg].pack("na*x")
return packet
end
end
Tuesday, March 17, 2009
UDP.rb
First step for my TFTP app is to build a simple UDP class.
UDP is a connectionless datagram protocol. You can bundle up some data, send it off to a target machine, and forget about the whole thing. It might not even make it to the destination; nobody cares. This has led the masses to assume that UDP is Unreliable. Consider, however, that UNIX uses UDP for internal messaging protocols. Also consider that, with just a small amount of effort, one can make lock-step communications with ACKing. This is how most networked games push their data around -- TCP would be unacceptable; it's a resource hog. And I always prefer to conserve my resources.
Two methods: send() and recv(). How much simpler can you get? I think the lack of a "connection" is a strength of UDP: the thing is just bare bones. I love that.
Here's some quick-and-dirty test code:
UDP is a connectionless datagram protocol. You can bundle up some data, send it off to a target machine, and forget about the whole thing. It might not even make it to the destination; nobody cares. This has led the masses to assume that UDP is Unreliable. Consider, however, that UNIX uses UDP for internal messaging protocols. Also consider that, with just a small amount of effort, one can make lock-step communications with ACKing. This is how most networked games push their data around -- TCP would be unacceptable; it's a resource hog. And I always prefer to conserve my resources.
require "socket"
class UDP
def send( msg, host, port, flags=0 )
sock = UDPSocket.new
sock.send( msg, flags, host, port )
sock.close
end
def recv( port, maxblocksize )
sock = UDPSocket.new
sock.bind( "localhost", port )
msg = sock.recv( maxblocksize )
p sock.addr
sock.close
return msg
end
end
Two methods: send() and recv(). How much simpler can you get? I think the lack of a "connection" is a strength of UDP: the thing is just bare bones. I love that.
Here's some quick-and-dirty test code:
client = UDP.new
client.send( msg, server_addr, server_port )
server = UDP.new
loop do
msg = server.recv( server_port, maxbytes )
p msg
exit if msg.chomp.eql?( 'exit' )
sleep 1
end
Monday, March 16, 2009
Old Protocols for a New Web
When I say "New Web" I mean a hypothetical, non-existent internet that uses existing technology in novel ways to improve efficiency and presentation. And Ruby's a great language for prototyping this.
My first project with Ruby is an implementation of TFTP. TFTP is a poor man's FTP. It has three RFC's, all short and sweet. Here are the things that makes it nice:
(1) simple. It's a small protocol, and so anyone can implement it. It's so small and so useful that it's used to boot up routers.
(2) proven. Again, it's one of the first applications ported to a new server. It's how servers get upgraded. That should tell you something about its utility.
(3) relatively non-hackable. Again, due to its simplicity. Especially if it's read-only, i.e. doesn't support writing files.
(4) fast. Because it's built on UDP, there's very low overhead, and no expensive handshaking, TCP nailup costs, etc.
(5) svelte. Again, because it uses UDP, there's no TCP nailup cost, and other associated expensive processing.
(6) synchronous. Because UDP has a willy-nilly transmission style, TFTP synchronizes transfer with numbered packets and does its own ACKs, retransmits, etc. If you thought UDP was unreliable, well, there's ways around that, and those ways are easy.
I'm still working on the implementation, but preliminary results are encouraging. The only discouraging thing is that servers generally lock down UDP transmissions as a rule. That's just something I'm going to have to face: it's not secure as-is, what with the ability to write files at will into the target file system.
BUT, what I want to do is implement browser functionality using TFTP as the transport mechanism. This means it's a read-only protocol... or, more correctly, "writes" are translated as "posts" rather than file transfers. So, no writing files directly into the file system. This puts security on par with current browsers.
Of course, on top of TFTP would have to be a new kind of browser, but that's a nontrivial task that I'll leave for the future. Perhaps it can just be a plugin for Firefox. And then, there's the question of what the presentation layer is going to be. CSS and HTML? Sure, but the scientific community is not served by these hacked styles. I want a TeX display layer. Once again, that's another nontrivial task that I'll have to leave for the future. I'll be happy just to get TFTP working.
My first project with Ruby is an implementation of TFTP. TFTP is a poor man's FTP. It has three RFC's, all short and sweet. Here are the things that makes it nice:
(1) simple. It's a small protocol, and so anyone can implement it. It's so small and so useful that it's used to boot up routers.
(2) proven. Again, it's one of the first applications ported to a new server. It's how servers get upgraded. That should tell you something about its utility.
(3) relatively non-hackable. Again, due to its simplicity. Especially if it's read-only, i.e. doesn't support writing files.
(4) fast. Because it's built on UDP, there's very low overhead, and no expensive handshaking, TCP nailup costs, etc.
(5) svelte. Again, because it uses UDP, there's no TCP nailup cost, and other associated expensive processing.
(6) synchronous. Because UDP has a willy-nilly transmission style, TFTP synchronizes transfer with numbered packets and does its own ACKs, retransmits, etc. If you thought UDP was unreliable, well, there's ways around that, and those ways are easy.
I'm still working on the implementation, but preliminary results are encouraging. The only discouraging thing is that servers generally lock down UDP transmissions as a rule. That's just something I'm going to have to face: it's not secure as-is, what with the ability to write files at will into the target file system.
BUT, what I want to do is implement browser functionality using TFTP as the transport mechanism. This means it's a read-only protocol... or, more correctly, "writes" are translated as "posts" rather than file transfers. So, no writing files directly into the file system. This puts security on par with current browsers.
Of course, on top of TFTP would have to be a new kind of browser, but that's a nontrivial task that I'll leave for the future. Perhaps it can just be a plugin for Firefox. And then, there's the question of what the presentation layer is going to be. CSS and HTML? Sure, but the scientific community is not served by these hacked styles. I want a TeX display layer. Once again, that's another nontrivial task that I'll have to leave for the future. I'll be happy just to get TFTP working.
Subscribe to:
Posts (Atom)