Showing posts with label TFTP. Show all posts
Showing posts with label TFTP. Show all posts

Friday, March 2, 2012

Time for a new internet browser

Time to be an old grump for a moment.

I've said it before, I'll say it again.  It's time to rewrite the browser.  Invent, create, realize a new way of browsing the internet.

Forget HTML, JavaScript, FlashPlayer et al.  Computers are powerful; why aren't browsers?  Why can't you develop on the browser the same way you develop directly onto the operating system?  Why isn't there a virtual machine to which you may directly target compilers?  That way, you have your cake and can eat it, too.

I'm not saying the browser should be an operating system; it's an application.  However, it should integrate with operating systems.  For example, security is an OS problem; it should not be an application's problem.  Why solve the same problem over and over again?  There are realtime impacts to this: HTTP and HTTPS are heavy compared to TFTP.

I am saying that HTML is annoying.  I don't think HTML5 will solve that problem - at least, it won't solve it anytime soon.  HTML is to the browser like Java is to the OS: it's a language, a display and layout language.  It defines the View.

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.


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.