List Info

Thread: Re: "packet" framing




Re: "packet" framing
user name
2007-10-15 04:19:21
On Sun, Oct 14, 2007 at 01:52:48PM -0700, Bill Kelly wrote:
> For what it's worth, I'm currently implementing
something similar,
> which I'll release open source (non-GPL.)
> 
> I'm not using DRb, because I need Ruby <--> C++
communication, not
> just Ruby <--> Ruby.
> 
> My protocol is focused on fast remote procedure call
(over TCP or
> UDP) between both Ruby and non-Ruby nodes.  However,
the data types
> understood by the protocol are deliberately
Ruby-oriented.

I had some thoughts along these lines a while ago, as I
needed a lightweight
IPC interface between Ruby and Perl. Actually the Perl part
of this has
evaporated now, so I haven't needed to develop this
further.

But for what it's worth, I have some suggestions if you're
looking to
implement a better-than-DRb for heterogenous applications.

(1) Make the basic mandatory data type the
"string". Allow the two ends to
negotiate additional encodings, such as binary integers,
IEEE floats,
arrays, Ruby Marshal dumps, Perl Storable, PHP serialize
etc; but if both
ends don't support anything else, fallback to string
representation.

A bitmap representing known types would be a simple way to
do this. Just AND
the sender and receiver capability bitmaps to get the
acceptable common
ones. Then for any particular object the sender can choose
their preferred
representation from among the common ones.

[Keeping the list of mandatory types small would make the
protocol very
useful in embedded devices]

(2) Like DRb, keep the low-level distinction between
"success" and "fail"
results. This means you can have a method which *returns* an
exception
object be distinct from a method which *raises* an exception
during its
execution. This might be done by having "execution
failure" be a basic type
of its own.

(3) Make "proxy object" be a basic type too (a la
DRbUndumped (*)). This
allows the receiver to invoke methods on objects held at the
caller. Making
this a basic type means that a Perl receiver could invoke a
Ruby proxy
object without having to understand how to unmarshal a Ruby
DRbObject.

(4) Include support for method calls to be sent in *both*
directions down
the same socket; that is, have separate 'request' and
'response' message
types which can be distinguished on the wire, and allow
"servers" to send
new requests back to "clients". This means that
callbacks can be made back
down the same socket as the incoming request came on, which
in turn means
that it will work properly through NAT firewalls - something
which DRb is
miserable at.

[This does rely on the sender keeping the connection nailed
up, however.
Perhaps each proxy object should also contain an
"alternative callback
address" to be used in the event that the original
connection has been
lost]

(5) Tag each request and response with an ID, so that you
can send multiple
overlapping requests and responses down the same socket.
This avoids what
DRb does, which is opening multiple transport-layer
connections to the same
target if concurrent requests to the same target are made
from separate
threads (see DRbConn)

A simple embedded client or server can always implement only
simple
request-response ordering if it wishes.

(5a) Dividing large requests into chunks of, say, 64KB might
make for better
interleaving in this case.

(6) Include support for running over Unix domain sockets
(surprisingly
awkward with DRb)

(7) Include support for running over stdin/stdout, e.g. one
process which
talks to another process that it started using popen().

Possibly also useful:

(8) Support for running over TLS (possibly upgrading the
connection after
the initial handshake)

(9) Simple [possibly mutual] authentication at start of the
connection

(10) Support for running over HTTP (and FastCGI), although
that would
enforce calls to be unidirectional.

(11) Like DRb, you'll probably need some concept of a
"head object" or
"default object", to which you can send requests
if you don't know the
object ID of any other object on the peer. For simple
servers you only want
to expose one object anyway. For more complex servers the
application writer
can provide a directory object; I don't think you need to
worry about this
within the protocol itself.

Regards,

Brian.

(*) If this doesn't mean anything to you, google for
DRbTutorial.
Unfortunately the RubyGarden wiki appears to be permanently
down these days,
but you may be able to find a cached copy.
_______________________________________________
Eventmachine-talk mailing list
Eventmachine-talkrubyforge.org
http://rubyforge.org/mailman/listinfo/eventmachine-talk

Bug report for JMeter
country flaguser name
United States
2007-10-15 01:08:28
+-----------------------------------------------------------
----------------+
| Bugzilla Bug ID                                           
               |
|    
+-----------------------------------------------------------
----------+
|     | Status: UNC=Unconfirmed NEW=New         ASS=Assigned
               |
|     |         OPN=Reopened    VER=Verified    (Skipped
Closed/Resolved)   |
|     |  
+-----------------------------------------------------------
------+
|     |   | Severity: BLK=Blocker     CRI=Critical   
MAJ=Major             |
|     |   |           MIN=Minor       NOR=Normal     
ENH=Enhancement       |
|     |   |  
+-----------------------------------------------------------
--+
|     |   |   | Date Posted                                 
               |
|     |   |   |         
+--------------------------------------------------+
|     |   |   |          | Description                      
               |
|     |   |   |          |                                  
               |
|11536|Ass|Enh|2002-08-07|Graph Results's throughput
calculation includes id|
|15468|New|Enh|2002-12-18|Variable expansion in posted files
in HTTPSampler |
|15999|New|Enh|2003-01-12|Show Results Tree is too
HTTP-centric             |
|16370|New|Enh|2003-01-23|HTTP Request log                  
               |
|16886|New|Enh|2003-02-07|Recorded requests shouldn't
duplicate info in HTTP|
|17248|New|Enh|2003-02-20|Graph Improvements                
               |
|17252|Ass|Enh|2003-02-20|HTML Link Parser seems not work
properly.         |
|19128|Ass|Enh|2003-04-17|need to support multi files
upload.               |
|21695|New|Enh|2003-07-17|Unix jmeter start script assumes
it is on PATH, no|
|22076|New|Enh|2003-08-01|would like to be able to delete
all server/ip and |
|22225|New|Enh|2003-08-07|non GUI mode: unable to load a
custom property fil|
|22510|New|Maj|2003-08-18|SSL Manager does not handle
multiple client certif|
|24480|New|Enh|2003-11-06|There is no good way to set
checkbox based items u|
|25144|New|Enh|2003-12-02|Have the Restart button in the
HTTP Proxy show up |
|25209|New|Min|2003-12-04|missed refresh of horizontal
scrollbar when switch|
|25430|New|Enh|2003-12-11|Recording Controller to populate
HTTP Authorisatio|
|27112|New|Enh|2004-02-20|User Parameters should use
scrollbars             |
|27481|New|Enh|2004-03-05|Allow some parameters to be passed
to remote serve|
|27895|New|Enh|2004-03-24|badly formatted JDBC output (a
regression w.r.t. 1|
|28502|New|Enh|2004-04-20|HTTP Resource Cache               
               |
|29331|New|Enh|2004-06-01|how to load test java applet using
JMeter         |
|29352|New|Enh|2004-06-03|Use external store to hold samples
during distribu|
|29603|New|Enh|2004-06-16|Custom component developers need
own resource bund|
|29708|New|Enh|2004-06-21|startup delay by JMeterThread
initialization      |
|30563|New|Enh|2004-08-10|Thread Group should have a restart
loop option on |
|30945|New|Enh|2004-08-30|Remote Exit does not shut down the
rmi registry.  |
|31666|New|Enh|2004-10-12|writing sampleresults to databases
               |
|32494|New|Enh|2004-12-02|Enhancement - scheduler should be
added to Test Pl|
|33305|New|Enh|2005-01-31|Visual diff and merge
functionality for JMeter scr|
|33878|New|Enh|2005-03-07|Function caching as option        
               |
|33940pn|Nor|20
05-03-09|Throughput value and Graph Results
"Graphing" don'|
|33954|New|Min|2005-03-11|Stack Overflow in If/While
controllers            |
|34095|New|Min|2005-03-21|Duplicate samples not elminated
when writing to CS|
|34287|New|Enh|2005-04-04|Some samples are not recorded (RMI
connection erro|
|34321|New|Enh|2005-04-06|password encryption for HTTP
Authorization Manager|
|35059|New|Maj|2005-05-25|RuntimeController not working
correctly           |
|35593|New|Enh|2005-07-03|Commons chain sampler             
               |
|35670|New|Enh|2005-07-09|Default parameters not displayed  
               |
|35915|New|Enh|2005-07-28|MonitorResults does not write
results n CSV format|
|35954|New|Enh|2005-07-31|New Pre-Processor called
Randomizer               |
|36227|New|Enh|2005-08-17|Non-Threadsafe Controller         
               |
|36378|New|Enh|2005-08-26|[PATCH] A "Thread
Watcher" Listener               |
|36619pn|Nor|20
05-09-12|Thread group Stop Test doesn't work with Loop
coun|
|36694|New|Enh|2005-09-17|substitute a value in the input
XML for webservice|
|36721|New|Enh|2005-09-20|webMethods Sampling Protocol
Extensions           |
|36726|New|Enh|2005-09-20|Activate "ctrl F"
shortcut to search a text in the|
|36761|New|Enh|2005-09-21|Choose if  "patterns to
test" are regular expressi|
|36931|New|Enh|2005-10-05|Printable Version of the Users
Manual             |
|37073|New|Enh|2005-10-13|Lacking Poisson timer             
               |
|37124|New|Enh|2005-10-17|Need error feedback in the GUI,
noticed this by ac|
|37155|New|Enh|2005-10-19|Testplan: Stop... Continue....    
               |
|37156|New|Enh|2005-10-19|Formatted view of Request in
Results Tree         |
|37160|New|Enh|2005-10-19|Scalable distributed testing      
               |
|37278|Inf|Enh|2005-10-27|Include Controller: File Name
field doesn't suppor|
|37525|New|Enh|2005-11-16|Web service sampler does not
support multipart req|
|38115|Inf|Nor|2006-01-04|decode from encoded string by IE  
               |
|38384|New|Enh|2006-01-25|POP3/SMTP Sampler with TLS/SSL    
               |
|38387|New|Enh|2006-01-25|allow to read(/send) mail messages
encrypted/signe|
|38576|New|Enh|2006-02-08|Well documented support for
ASP.NET idiosyncransie|
|38778|New|Enh|2006-02-24|Increment should be added in While
Controller     |
|38816|Ass|Enh|2006-03-01|"Build Monitor test
plan" documentation enhancemen|
|38832|New|Nor|2006-03-02|webservice request sampler adding
xmlnsmlns 
   |
|39036|Inf|Nor|2006-03-20|Thread Deadlock using Graph
Results               |
|39219|New|Nor|2006-04-06|HTTP Server: You can't stop it
after File->Open   |
|39509|New|Nor|2006-05-08nce-only
controller running twice                |
|39642|Ass|Enh|2006-05-23|Need a sampler forJMX
mbean-servers.              |
|39812|New|Blk|2006-06-14|Problem with
Webservice(SOAP)Request  over https  |
|39969|New|Enh|2006-07-05|Allow exporting of aggregate
results              |
|40011|New|Enh|2006-07-11|New Elements for use in JMeter    
               |
|40045|Ass|Enh|2006-07-14|Results monitor may select wrong
connector if more|
|40149|New|Enh|2006-08-01|Feature to write a Jmeter variable
to a file      |
|40181|Ass|Enh|2006-08-03|Add a new Session Bean protocol
extension         |
|40229|Inf|Nor|2006-08-11|Nested IfControllers failing on
2nd run           |
|40424|New|Enh|2006-09-06|Web Services proxy                
               |
|40499|New|Enh|2006-09-13|Need to be able to simulate
abortive connection re|
|40671|New|Cri|2006-10-03|IncludeController not working in
Jmeter 2.2       |
|40750|New|Nor|2006-10-12|Behaviour when TCPSampler sockets
are closed by re|
|40757|New|Maj|2006-10-13|Web Service(SOAP) Request Response
Time           |
|40850|New|Maj|2006-10-31|- Memory leak in all BeanShell
components         |
|40934|New|Nor|2006-11-09|CSV Data Set Config parameters
cannot be used in s|
|40961|New|Enh|2006-11-13|Maintain constant number of
clients after assertio|
|40973|New|Nor|2006-11-14|[View Results Tree] component
failed when generate|
|41028|New|   |2006-11-23|JMeter RMI distributed testing
doesn't alert the u|
|41108|Ass|   |2006-12-04|Stop Test isn't honored during
rampup period      |
|41110|New|Enh|2006-12-05|Jmeter does not record calculated
values, such as |
|41209|New|Enh|2006-12-19|JLabeled* and ToolTips            
               |
|41210|Inf|Enh|2006-12-19|Latency time is not included in
the summary report|
|41286|New|Nor|2007-01-03|Include controller problems in
Jmeter 2.1.1.      |
|41293|New|Enh|2007-01-04|Allow multi-level Thread Groups   
               |
|41319|New|Nor|2007-01-08|Parmeter value being URL decoded
in URLRewritingMo|
|41418|New|Enh|2007-01-19|Excludes timer duration from
Transaction Controlle|
|41545|Inf|Enh|2007-02-05|Enhancement to integrate soapui
into Soap/XMLRPC s|
|41566|New|Enh|2007-02-08|Require a method of disabling HTTP
Request Default|
|41788|New|Enh|2007-03-07|Log viewer (console window) needed
as an option   |
|41800|New|Enh|2007-03-09|Parser for parsing the CSV results
using JMeter An|
|41845|Inf|Enh|2007-03-15|Sorting the controllers' items in
context menu    |
|41878|Inf|Maj|2007-03-17|JMeter GUI crashes when performing
SOAP requests  |
|41917|New|Enh|2007-03-21|Restructure HTTP Request GUI, to
make it simpler a|
|41921|New|Maj|2007-03-21|samplers store all output, even
when arbitrarily l|
|42012|New|Min|2007-04-01|Variable filenames with remote
tests do not get pr|
|42141|New|Min|2007-04-17|[Usability] Save as doesn't
replace forbidden char|
|42178|New|Enh|2007-04-20|CSV files do read from begining
when "Run each Thr|
|42204|New|Enh|2007-04-23|add current value of a parameter
as column        |
|42205|New|Enh|2007-04-23|expand/collaps multiple selected
nodes            |
|42243|New|Enh|2007-04-25|Loading a test plan fully expand
the treeview     |
|42245|New|Enh|2007-04-25|Show clear passwords in HTTP
Authorization Manager|
|42246|New|   |2007-04-25|Need for a 'auto-scroll' option in
"View Results T|
|42248|New|Enh|2007-04-25|Need undo-redo support            
               |
|42342|New|Enh|2007-05-05|Allow uploading of inline content
by FTP Request S|
|42428|New|Enh|2007-05-15|Workbench not saved with Test Plan
               |
|42538|New|Enh|2007-05-29|No "duplicate" entry in
context menu              |
|42540|New|   |2007-05-29|HCI: Inconsistent position of
"Close" in File menu|
|42555|Ass|Min|2007-05-31|[I18N] Proposed corrections for
the french transla|
|42637|Ass|Enh|2007-06-11|add non-POST method support to the
SOAP/XML-RPC sa|
|42638|New|Min|2007-06-11|HTTP sampler file-sending only
works with some of |
|42717|Inf|Enh|2007-06-21|webservice soap sampler does not
recognize name sp|
|42784|New|Enh|2007-06-30|Show the number of errors logged
in the GUI       |
|42801|Inf|Nor|2007-07-03|Results Visualization: Throughput
is falsely calcu|
|42833|New|Enh|2007-07-07|Argument class to use
LinkedHashMap to preserve or|
|42837|New|Enh|2007-07-09|Provide link between .jmx and .jtl
files          |
|42867|New|Nor|2007-07-12nly
default parameters of Java Request Samplers a|
|43023|New|Nor|2007-08-03|Support HTTP1.1 with WebServices  
               |
|43024|New|Nor|2007-08-03|WebServices Cookie support        
               |
|43119|New|Enh|2007-08-14|Configuration of 'Save Responses
to a file' to all|
|43130|New|Nor|2007-08-15|HTTP Request sampler does not POST
file if there a|
|43168|New|Enh|2007-08-20|Exception when running multiple
tests in same remo|
|43180|New|Enh|2007-08-21|Eliminate GUI class-loading in
non-GUI mode       |
|43284|New|   |2007-09-02|Centralise use of ".jmx"
and ".jtl" etc           |
|43288|New|Nor|2007-09-02|JLabeledRadio.getText() is
language dependent     |
|43293|New|Nor|2007-09-03|Java Request fields not cleared
when creating new |
|43294|New|Nor|2007-09-03|XPath Extractor namespace problems
               |
|43360|New|Nor|2007-09-12|Huge size of test elements when
loading a script  |
|43363|New|Enh|2007-09-12ptions
for compressed content                    |
|43379|New|Enh|2007-09-13|new controller working like
switchcontroller but r|
|43380|New|Enh|2007-09-13|override "download embedded
ressources" for all ht|
|43381|New|Enh|2007-09-13|view results tree grouping results
per threadgroup|
|43382|New|Enh|2007-09-13|configure tidy output (warnings,
errors) in proper|
|43384|New|Enh|2007-09-13|using semaphores in jmeter (block
critical regions|
|43385|New|Enh|2007-09-13|set individual read and connect
timeout for java h|
|43407|New|Enh|2007-09-17|if-else controller                
               |
|43427|New|Nor|2007-09-19|Simple Controller is only partly
executed in loop |
|43431|New|Nor|2007-09-19|ConcurrentModificationException in
StandardJMeterE|
|43450|New|Nor|2007-09-21|Listeners/Savers assume
SampleResult count is alwa|
|43484|New|Nor|2007-09-26|Remote Statistical mode needs to
collect min/max s|
|43485|New|Enh|2007-09-26|Ability to specify keepalives on
XML/RPC request  |
|43539|New|Maj|2007-10-03|Monitor results are different in
Non-GUI Mode     |
|43545|New|Nor|2007-10-03|AbstractVisualizer should
implement TestElement in|
|43549|New|Enh|2007-10-04|Enhancing FTP Request with chmod
or other unix com|
|43556|New|Nor|2007-10-04|JMeter Proxy Server               
               |
|43585|New|Nor|2007-10-10|CSV file format does not support
delimiters in fie|
|43612|New|Nor|2007-10-12|HTTP PUT does not honor request
parameters        |
+-----+---+---+----------+----------------------------------
----------------+
| Total  151 bugs                                           
               |
+-----------------------------------------------------------
----------------+

------------------------------------------------------------
---------
To unsubscribe, e-mail: jmeter-dev-unsubscribejakarta.apache.org
For additional commands, e-mail: jmeter-dev-helpjakarta.apache.org


Re: "packet" framing
country flaguser name
United States
2007-10-15 04:51:07
----- Original Message ----- 
From: "Brian Candler" <B.Candlerpobox.com>
To: <eventmachine-talkrubyforge.org>
Sent: Monday, October 15, 2007 2:19 AM
Subject: Re: [Eventmachine-talk] "packet" framing


> On Sun, Oct 14, 2007 at 01:52:48PM -0700, Bill Kelly
wrote:
>> For what it's worth, I'm currently implementing
something similar,
>> which I'll release open source (non-GPL.)
>> 
>> I'm not using DRb, because I need Ruby <-->
C++ communication, not
>> just Ruby <--> Ruby.
>> 
>> My protocol is focused on fast remote procedure
call (over TCP or
>> UDP) between both Ruby and non-Ruby nodes. 
However, the data types
>> understood by the protocol are deliberately
Ruby-oriented.
> 
> I had some thoughts along these lines a while ago, as I
needed a lightweight
> IPC interface between Ruby and Perl. Actually the Perl
part of this has
> evaporated now, so I haven't needed to develop this
further.

Dude, thanks, I'm <3

(My context is quake2 100hz 3000 mile round trip UDP
packets,)

> But for what it's worth, I have some suggestions if
you're looking to
> implement a better-than-DRb for heterogenous
applications.
> 
> (1) Make the basic mandatory data type the
"string". Allow the two ends to
> negotiate additional encodings, such as binary
integers, IEEE floats,
> arrays, Ruby Marshal dumps, Perl Storable, PHP
serialize etc; but if both
> ends don't support anything else, fallback to string
representation.

Dude, I'm with that, but I felt that most RPC calls have
OpenGL{ ..... }

> 
> A bitmap representing known types would be a simple way
to do this. Just AND
> the sender and receiver capability bitmaps to get the
acceptable common
> ones. Then for any particular object the sender can
choose their preferred
> representation from among the common ones.
> 
> [Keeping the list of mandatory types small would make
the protocol very
> useful in embedded devices]

Dude, this is already netstrings 

<3

I know mandatory types can be small if one goes for
netstrings 

That may be the approach

++good 
_______________________________________________
Eventmachine-talk mailing list
Eventmachine-talkrubyforge.org
http://rubyforge.org/mailman/listinfo/eventmachine-talk

Re: "packet" framing
user name
2007-10-15 06:45:26
On Mon, Oct 15, 2007 at 02:51:07AM -0700, Bill Kelly wrote:
> > (1) Make the basic mandatory data type the
"string". Allow the two ends to
> > negotiate additional encodings, such as binary
integers, IEEE floats,
> > arrays, Ruby Marshal dumps, Perl Storable, PHP
serialize etc; but if both
> > ends don't support anything else, fallback to
string representation.
> 
> Dude, I'm with that, but I felt that most RPC calls
have
> OpenGL{ ..... }

Well, of course what I wrote was based on what *I* would
have found useful


I'm not familiar with the OpenGL API; do you just want to
call methods
OpenGLfoo(x,y,z) where x,y,z are primitive types like
integers? Or do you
need a more complex data representation (arrays of primitive
types? hashes
of primitive types? more than that?)

> > A bitmap representing known types would be a
simple way to do this. Just AND
> > the sender and receiver capability bitmaps to get
the acceptable common
> > ones. Then for any particular object the sender
can choose their preferred
> > representation from among the common ones.
> > 
> > [Keeping the list of mandatory types small would
make the protocol very
> > useful in embedded devices]
> 
> Dude, this is already netstrings 

Hmm, that wasn't quite what I was thinking of, and RPC is a
different layer
anyway. (Aside: netstrings aren't particularly easy to parse
for a binary
protocol. Personally I'd go for a 4-byte length in network
order. It has a
limit of 4GB, but how many RPC calls do you make with
>4GB of copy-by-value
arguments? 

Anyway, what I was thinking off was something like this.

1. client opens TCP connection

 ------->  (4 byte magic) (4 byte capability bitmap)
 <-------  (4 byte magic) (4 byte capability bitmap)

2. both ends AND their capability bitmaps. If the TLS bit is
set, they
both start TLS negotiation (in client or server mode
depending on who
initiated the connection). From this point onwards the
protocol is entirely
symmetrical.

3. when either side wants to make an RPC, they send a
message something
like this:

 ------->  1 byte tag: "request"
           4 bytes: request ID
           4 bytes: object ID  (if zero: default object)
           4 bytes: number of arguments, first argument is
method name
           number of arguments x
               1 byte: type
               4 bytes: length
               N bytes: data

The 'type' chosen for each value would correspond to one of
the bit
positions in the capability bitmap.

[Note: it may be more efficient in some situations to round
everything up to
4 byte boundaries, this could be a capability flag too]

4. the response at some point later would be

 <-------  1 byte tag: "response"
           4 bytes: request ID
           1 byte: type
           4 bytes: length
           N bytes: data

The basic types would be:

(0) String. Payload is sequence of N bytes of data. 8-bit
clean.

(1) Remote execution error. The N bytes are a string
containing info
    to help diagnosis (e.g. backtrace). Only used as a
return value.

(2) Proxy object. The data payload contains 4 bytes of
object ID, and
    the remainder is the object origin URI.

(3) nil (value is ignored)

(4) boolean (value is 0 for false, 1 for true)

(5) signed integer (value is big-endian binary)
    [maybe should have a fixed 4-byte version for ease of
decoding?]

... extend this list as you see fit

Then at the sender side you marshal using the 'best'
representation
supported by the sender. A Ruby implementation might look
something like
this:

CAP_STRING = 0
CAP_ERROR = 1
CAP_PROXY = 2
CAP_NIL = 3
CAP_BOOL = 4
CAP_LONG = 5
CAP_RUBY = 6

class Object
  def to_tinyrpc(capability)
    if capability[CAP_RUBY] > 0
      [CAP_RUBY, Marshal.dump(self) rescue
Marshal.dump(Proxy.new(self))]
    else
      [CAP_STRING, to_s]  # best we can do
    end
  end
end

class String
  def to_tinyrpc(capability)
    [CAP_STRING, self]  # always use the native String
representation
  end
end

class NilClass
  def to_tinyrpc(capability)
    if capability[CAP_NIL] > 0  # prefer the native Nil
representation
      [CAP_NIL, ""]
    elsif capability[CAP_RUBY] > 0
      [CAP_RUBY, Marshal.dump(nil)]
    else
      [CAP_STRING, ""]
    end
  end
end

class Fixnum
  def to_tinyrpc(capability)
    if capability[CAP_LONG] > 0 and self >=
-0x80000000 and self <= 0x7fffffff
      [CAP_LONG, [self].pack("N")]
    else
      [CAP_STRING, to_s]
    end
  end
end

You get the idea. The RPC caller would then be something
like:

  def method_missing(*args)
    socket.write [TAG_REQUEST, reqid, ref,
args.size].pack("NNNN")
    args.each do |arg|
      tag, data = arg.to_tinyrpc(capability)
      socket.write [tag, data.size].pack("NN")
      socket.write data
    end
    # for synchronous RPC: start a thread, wait for the
response, then
    # return the response to the caller
  end

I'm not saying you shouldn't write a domain-specific
solution for your
needs; I just think this approach would encourage RPC
interoperability. Of
course there's always XMLRPC and SOAP, so perhaps nobody
wants another
solution - but both these are expensive, and neither maps
well to the domain
which DRb seeks to address. DRb, meanwhile, is very
Ruby-specific.

Regards,

Brian.
_______________________________________________
Eventmachine-talk mailing list
Eventmachine-talkrubyforge.org
http://rubyforge.org/mailman/listinfo/eventmachine-talk

Re: "packet" framing
country flaguser name
United States
2007-10-15 15:18:41
From: "Bill Kelly" <billkcts.com>
> Dude,
> Dude,
> Dude,

Er.... pardon my redundancy. 


From: "Brian Candler" <B.Candlerpobox.com>
>
> Hmm, that wasn't quite what I was thinking of, and RPC
is a different layer
> anyway. (Aside: netstrings aren't particularly easy to
parse for a binary
> protocol. Personally I'd go for a 4-byte length in
network order. It has a
> limit of 4GB, but how many RPC calls do you make with
>4GB of copy-by-value
> arguments? 
> 
> Anyway, what I was thinking off was something like
this.
> 
> 1. client opens TCP connection
> 
> ------->  (4 byte magic) (4 byte capability bitmap)
> <-------  (4 byte magic) (4 byte capability bitmap)
> 
> 2. both ends AND their capability bitmaps. If the TLS
bit is set, they
> both start TLS negotiation (in client or server mode
depending on who
> initiated the connection). From this point onwards the
protocol is entirely
> symmetrical.
> 
> 3. when either side wants to make an RPC, they send a
message something
> like this:
> 
> ------->  1 byte tag: "request"
>           4 bytes: request ID
>           4 bytes: object ID  (if zero: default
object)
>           4 bytes: number of arguments, first argument
is method name
>           number of arguments x
>               1 byte: type
>               4 bytes: length
>               N bytes: data
> 
> The 'type' chosen for each value would correspond to
one of the bit
> positions in the capability bitmap.
> 
> [Note: it may be more efficient in some situations to
round everything up to
> 4 byte boundaries, this could be a capability flag
too]
> 
> 4. the response at some point later would be
> 
> <-------  1 byte tag: "response"
>           4 bytes: request ID
>           1 byte: type
>           4 bytes: length
>           N bytes: data
> 
> The basic types would be:
> 
> (0) String. Payload is sequence of N bytes of data.
8-bit clean.
> 
> (1) Remote execution error. The N bytes are a string
containing info
>    to help diagnosis (e.g. backtrace). Only used as a
return value.
> 
> (2) Proxy object. The data payload contains 4 bytes of
object ID, and
>    the remainder is the object origin URI.
> 
> (3) nil (value is ignored)
> 
> (4) boolean (value is 0 for false, 1 for true)
> 
> (5) signed integer (value is big-endian binary)
>    [maybe should have a fixed 4-byte version for ease
of decoding?]
> 
> ... extend this list as you see fit
> 
> Then at the sender side you marshal using the 'best'
representation
> supported by the sender. A Ruby implementation might
look something like
> this:
> 
> CAP_STRING = 0
> CAP_ERROR = 1
> CAP_PROXY = 2
> CAP_NIL = 3
> CAP_BOOL = 4
> CAP_LONG = 5
> CAP_RUBY = 6
> 
> class Object
>  def to_tinyrpc(capability)
>    if capability[CAP_RUBY] > 0
>      [CAP_RUBY, Marshal.dump(self) rescue
Marshal.dump(Proxy.new(self))]
>    else
>      [CAP_STRING, to_s]  # best we can do
>    end
>  end
> end
> 
> class String
>  def to_tinyrpc(capability)
>    [CAP_STRING, self]  # always use the native String
representation
>  end
> end
> 
> class NilClass
>  def to_tinyrpc(capability)
>    if capability[CAP_NIL] > 0  # prefer the native
Nil representation
>      [CAP_NIL, ""]
>    elsif capability[CAP_RUBY] > 0
>      [CAP_RUBY, Marshal.dump(nil)]
>    else
>      [CAP_STRING, ""]
>    end
>  end
> end
> 
> class Fixnum
>  def to_tinyrpc(capability)
>    if capability[CAP_LONG] > 0 and self >=
-0x80000000 and self <= 0x7fffffff
>      [CAP_LONG, [self].pack("N")]
>    else
>      [CAP_STRING, to_s]
>    end
>  end
> end
> 
> You get the idea. The RPC caller would then be
something like:
> 
>  def method_missing(*args)
>    socket.write [TAG_REQUEST, reqid, ref,
args.size].pack("NNNN")
>    args.each do |arg|
>      tag, data = arg.to_tinyrpc(capability)
>      socket.write [tag, data.size].pack("NN")
>      socket.write data
>    end
>    # for synchronous RPC: start a thread, wait for the
response, then
>    # return the response to the caller
>  end
> 
> I'm not saying you shouldn't write a domain-specific
solution for your
> needs; I just think this approach would encourage RPC
interoperability. Of
> course there's always XMLRPC and SOAP, so perhaps
nobody wants another
> solution - but both these are expensive, and neither
maps well to the domain
> which DRb seeks to address. DRb, meanwhile, is very
Ruby-specific.

Hmm, interesting, thanks!

I hadn't thought about having capability flags at that
protocol level.

I'll admit I'm biased toward Ruby, and so I've simply
written C++ code
that can handle all the various Ruby types, including nil,
true, false,
etc.

On my previous implementation, Ruby -> C++ RPC was as
easy as:

class RubyContextCommBridge < BlankSlate
  def method_missing(*name_and_args)
    remote.query(name_and_args)
  end
end

And I want the new one to be similarly trivial from the Ruby
side.
(So I'm OK with hard-wiring the capabilities to fit Ruby's
types.)


>From Chuck Remes:
>
> And now, back to your regularly scheduled discussion
about reinventing
> RPC/RMI/RIPC/etc.

LOL  
Sorry for the noise 

Well if it helps for context, here is a recent conversation
about a game
protocol that is 10 years old this month:

[16:30] <R1CH> the bandwidth savings on the new
usercmd scaling add up pretty quick
[16:31] <R1CH> 33MB on quakdev
[16:31] <R1CH> and most people only recently updated
their clients
[16:42] <quadz> nifty
[16:43] <quadz> what sort of data is being scaled ?
[16:44] <R1CH> movement speeds
[16:44] <R1CH> the client can send anywhere between
-300 to 300 for x/y/z velocity
[16:44] <R1CH> usually requiring 6 bytes
[16:44] <R1CH> however i steal some unused bits in the
buttons byte to indicate if
the x/y/z are multiples of 5, if so, only send the 1 byte
and scale it on the server
[16:45] <R1CH> 1 byte might not seem like much
[16:45] <R1CH> but client packet rate is usually a lot
higher than server
[16:45] <R1CH> so it adds up quickly

Protocol 35 netcode has saved 56693514 bytes.
Protocol 35 compression has saved 89628522 bytes.
Protocol 35 usercommand scaling has saved 26026608 bytes.
R1Q2 playerstate quantization optimization has saved
37328413 bytes.
R1Q2 entity quantization optimization has saved 163290336
bytes.
R1Q2 custom delta management has saved 22637949 bytes.
R1Q2 sv_func_entities_hack has saved 0 bytes. (disabled)
Total byte savings: 395605342 (377.28 MB)

So from that perspective my current RPC protocol reinvention
seems 
incredibly decadent and wasteful.  


Regards,

Bill


_______________________________________________
Eventmachine-talk mailing list
Eventmachine-talkrubyforge.org
http://rubyforge.org/mailman/listinfo/eventmachine-talk

[1-5]

about | contact  Other archives ( Real Estate discussion Medical topics )