From: Brian Candler Date: 2007-05-09T20:56:22+09:00 Subject: Re: NetworkFacade 0.4 On Wed, May 09, 2007 at 05:28:56PM +0900, Florent Solt wrote: > Many other examples (Unix socket, SSL, Compression, Flickr, > Remember the milk, Netvibes) are explained here : > > http://network-facade.rubyforge.org/doc I can't find any documentation of the TCP protocol itself. Looking at the code, the call appears to be a four-byte length followed by a Marshal dump of [@uri.path[1..-1], name, args] and the response is a 4-byte length followed by a Marshal dump of a single object. This means that the protocol is similar to DRb, but different, i.e. not compatible :-( I can see a problem with this protocol: it's impossible to distinguish between a method returning an Exception object and a method raising an exception. There are certainly problems which DRb has which could do with solving. Chief in my mind these are: (1) Doesn't run easily over FastCGI, IO.popen and stdin/stdout, or Unix domain sockets. (2) Doesn't allow bi-directional method calls through a single connection, e.g. for use through a firewall and/or NAT and port forwarding. (3) Doesn't interoperate with non-Ruby applications. I would like to be able to carry strings and integers as plain strings. This would make it easy to interoperate with Perl, say. (4) Not easy to secure. (5) Large and complex implementation, not easy to understand, especially with regards to connection caching and what happens if connections are dropped. Your library addresses (4), (5) and part of (1). But I think (2) and (3) need careful thinking to produce a suitable protocol. As for (2), I'm not sure your protocol supports proxy objects at all, a.k.a. DRbUndumped, but please correct me if I'm wrong. I think a replacement protocol for DRb should have the following characteristics: * 'Requests' and 'Responses' explicitly marked as such, so that calls can be made in both directions down the same socket. * Each Request and Response to be tagged with an ID, so multiple overlapping calls can be multiplexed onto the same socket, meaning that only a single TCP connection needs to be kept open between a particular pair of hosts. * Ability to pass Undumped objects in such a way that the callback is either made back down the same socket, or to a global URI (the latter is what DRb does). The latter also allows the callback to be made independently, and avoids forming long chains of tunnels. (+) * Basic protocol uses only string encoding, allowing tiny implementation suitable for embedded devices etc, and cross-language interoperability. * Optionally enable other native marshalling protocols (e.g. Marshall, YAML, Perl Storable etc) if understood by both sides. Ideally negotiated. * Optional SASL authentication as well as, or instead of, SSL. This allows basic username/password authentication (AUTH PLAIN) which is simpler to configure than client certificates. * Optional synchronous mode (one request -> one response) for tunneling over HTTP or FastCGI and for simplistic implementations in embedded devices * Automatic establishment or re-establishment of dropped connections I also think that implementations should consider using an opaque key to identify each object, rather than it's object_id. For one thing, object_id's can be recycled; for another, it prevents people probing for random objects which have not been explicitly shared. Keeping a mapping table of opaque_key => object will prevent DRbUndumped objects from being garbage collected (although this may or may not be desirable) Just a few thoughts. Regards, Brian. (+) It would be useful to pass a different global URI depending on where you are connecting to. For example, if you are connecting outbound through the Internet, the global URI you expose may be your firewalls' outside IP or hostname and a port on the firewall which forwards inbound connections. To make this more transparent, it could be useful to auto-detect NAT. This could be done by passing your *actual* source IP and port inside the connection message; the far end would compare these to the *seen* source IP and port. IPSEC NAT traversal uses a similar mechanism.