summaryrefslogtreecommitdiff
path: root/host/mex
diff options
context:
space:
mode:
authorNicolas Schodet2011-03-30 20:08:34 +0200
committerNicolas Schodet2011-03-30 20:08:34 +0200
commit057180987cacfe47edbe21bf2f8c0573901ded2f (patch)
treece5eb7c68525ead0430d43051428a9234ebfa053 /host/mex
parentc9a004ed32389dd17167f19be7916ef9320e8e39 (diff)
host/mex, digital/avr/modules/host: add message type reservation, refs #157
Diffstat (limited to 'host/mex')
-rw-r--r--host/mex/__init__.py4
-rw-r--r--host/mex/doc/mex.txt21
-rw-r--r--host/mex/hub.py18
-rw-r--r--host/mex/node.py15
-rw-r--r--host/mex/test/test.py14
5 files changed, 64 insertions, 8 deletions
diff --git a/host/mex/__init__.py b/host/mex/__init__.py
index 1855d708..f87cf856 100644
--- a/host/mex/__init__.py
+++ b/host/mex/__init__.py
@@ -40,6 +40,10 @@ RSP = 3
"""RSP (response) message, response to a REQ message, only sent to the
requesting node."""
+RES = 4
+"""RES (reserve) message, sent to the hub to request a message type, sent to a
+node with the allocated message type."""
+
DEFAULT_ADDR = ('localhost', 2442)
HEADER_FMT = '!HB'
diff --git a/host/mex/doc/mex.txt b/host/mex/doc/mex.txt
index 4c8eb559..ef299d56 100644
--- a/host/mex/doc/mex.txt
+++ b/host/mex/doc/mex.txt
@@ -37,9 +37,8 @@ been handled (or discarded).
The minimum required information in a message is the message type. This is a
single byte (with some reserved values) which should be sufficient to decode
-the rest of the message. There is for the moment no central message type
-identifier repository, the developer is responsible to ensure no collision
-occurs.
+the rest of the message. Message types should be reserved by requesting them
+from the hub.
When the message is sent to another process, it is prepended with its size and
sequence number (which are not part of the message, neither its size). The
@@ -167,6 +166,22 @@ RSP
The receiving node will decapsulate the message and will use it as a
response to its request.
+RES
+ This is a message type reservation request.
+
+ When sent to the hub, it contains a reservation string which identify the
+ message type.
+
+ +------------+--------------------+
+ | RES (B: 4) | reservation string |
+ +------------+--------------------+
+
+ When sent to the node, it contains the allocated message type.
+
+ +------------+-----------------+
+ | RES (B: 4) | allocated mtype |
+ +------------+-----------------+
+
Programmer interface
====================
diff --git a/host/mex/hub.py b/host/mex/hub.py
index 4dd796a4..274f5448 100644
--- a/host/mex/hub.py
+++ b/host/mex/hub.py
@@ -36,6 +36,7 @@ class Hub:
self.log = log
self.clients = { }
self.next_client_id = 1
+ self.reserved_mtype = { }
self.date = 0
self.socket = socket.socket ()
self.socket.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -109,6 +110,18 @@ class Hub:
if c is not exclude:
c.send (msg)
+ def reserve (self, mtype_str):
+ """Reserve a message type."""
+ if mtype_str in self.reserved_mtype:
+ mtype = self.reserved_mtype[mtype_str]
+ else:
+ mtype = 0x20 + len (self.reserved_mtype)
+ self.reserved_mtype[mtype_str] = mtype
+ if self.log:
+ self.log ('[%d] reserve "%s" as %02x' % (self.date,
+ mtype_str, mtype))
+ return mtype
+
class Client:
def __init__ (self, hub, socket, id):
@@ -159,6 +172,11 @@ class Hub:
mr.push ('B', 0)
mr.push (m.pop ())
self.hub.clients[to].send (mr)
+ elif m.mtype == mex.RES:
+ mtype_str = m.pop ()
+ mr = Msg (mex.RES)
+ mr.push ('B', self.hub.reserve (mtype_str))
+ self.send (mr)
else:
self.hub.broadcast (m, self)
diff --git a/host/mex/node.py b/host/mex/node.py
index 8fcf9ae0..a1f226cd 100644
--- a/host/mex/node.py
+++ b/host/mex/node.py
@@ -122,6 +122,21 @@ class Node:
assert mtype not in self.__handlers
self.__handlers[mtype] = handler
+ def reserve (self, mtype_str):
+ """Request a message type reservation."""
+ # Send request.
+ res = Msg (mex.RES)
+ res.push (mtype_str)
+ self.send (res)
+ # Wait for response.
+ rsp = self.__recv ()
+ while rsp.mtype != mex.RES:
+ self.__dispatch (rsp)
+ rsp = self.__recv ()
+ # Return allocated message type.
+ mtype, = rsp.pop ('B')
+ return mtype
+
def schedule (self, date, action):
"""Schedule an action for the given date, return the event identifier."""
assert date > self.date
diff --git a/host/mex/test/test.py b/host/mex/test/test.py
index b9d06e00..91e49ee0 100644
--- a/host/mex/test/test.py
+++ b/host/mex/test/test.py
@@ -35,6 +35,8 @@ h = Hub (min_clients = 2, log = log)
def c1 ():
n = Node ()
+ mtype_oucouc = n.reserve ('oucouc')
+ mtype_coucou = n.reserve ('coucou')
def a (msg):
print 'oucouc'
nb, = msg.pop ('B')
@@ -42,7 +44,7 @@ def c1 ():
m = Msg (msg.mtype)
m.push ('B', nb)
n.response (m)
- n.register (0x82, a)
+ n.register (mtype_oucouc, a)
def b ():
assert False
eb = n.schedule (31, b)
@@ -50,7 +52,7 @@ def c1 ():
print 'hello'
n.cancel (eb)
n.schedule (28, c)
- m = Msg (0x81)
+ m = Msg (mtype_coucou)
n.send (m)
n.wait ()
@@ -58,13 +60,15 @@ f1 = Forked (c1)
def c2 ():
n = Node ()
+ mtype_oucouc = n.reserve ('oucouc')
+ mtype_coucou = n.reserve ('coucou')
def a (msg):
print 'coucou'
- n.register (0x81, a)
- m = Msg (0x82)
+ n.register (mtype_coucou, a)
+ m = Msg (mtype_oucouc)
m.push ('B', 42)
r = n.request (m)
- assert r.mtype == 0x82
+ assert r.mtype == mtype_oucouc
assert r.pop ('B') == (43,)
n.wait_async (42)
while not n.sync ():