~ubuntu-branches/ubuntu/jaunty/gdesklets/jaunty-proposed

« back to all changes in this revision

Viewing changes to utils/xdr.py

  • Committer: Bazaar Package Importer
  • Author(s): Loic Minier
  • Date: 2006-06-14 19:19:07 UTC
  • mfrom: (1.1.2 upstream) (2.1.1 dapper)
  • Revision ID: james.westby@ubuntu.com-20060614191907-yktrjkep30abmrfn
Tags: 0.35.3-4
Don't ship /usr/share/mime/mime.cache. (Closes: #373600)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: UTF-8 -*-
2
 
 
3
 
import struct
4
 
 
5
 
__doc__ = """
6
 
Transport of Data
7
 
 
8
 
 
9
 
 
10
 
Format of Transported Data
11
 
--------------------------
12
 
 
13
 
In order to communicate with external non-python programs, the xdr module
14
 
implements a very simple protocol à la XDR.
15
 
 
16
 
The send function expect variable length arguments of str type.
17
 
The arguments will be escaped, joint and packed into binary.
18
 
All the arguments have to be joint into a '\\n' delimited str.
19
 
 
20
 
e.g. send(s, "a", "b", "c") -> "a\\nb\\nc"
21
 
 
22
 
If one argument contains '\n' it has to be escaped
23
 
 
24
 
e.g. send(s, "a\\n", "b", "c") -> "a\\\\n\\nb\\nc"
25
 
 
26
 
If their are no arguments, an empty str is sent.
27
 
 
28
 
To be safely and efficiently exchanged, arguments are packed into the
29
 
following representation :
30
 
 
31
 
   0     1     2     3   ...
32
 
+-----+-----+-----+-----+-----+---+
33
 
| length n  |byte0|byte1|...| n-1 |
34
 
+-----+-----+-----+-----+-----+---+
35
 
|<-2 bytes->|<------n bytes------>|
36
 
 
37
 
 
38
 
The length is encoded into a two bytes unsigned integer in native
39
 
epresentation.
40
 
 
41
 
e.g. send(s, "a", "b", "c") -> "\\x05\\x00a\\nb\\nc" (05 00 61 0a 62 0a 63)
42
 
 
43
 
Recieved data has to be unpacked, splitted and unescaped.
44
 
"""
45
 
 
46
 
# we should have used xrdlib
47
 
# but i don't know if this add another dependency
48
 
# and a Packer object has to be created each call
49
 
# so it may be slower
50
 
# if we get issues with the current protocol, we should
51
 
# switch to xdrlib
52
 
 
53
 
# 64k is large enough
54
 
 
55
 
_HEADER_FORMAT = 'H'
56
 
_SIZEOF_HEADER = struct.calcsize(_HEADER_FORMAT)
57
 
 
58
 
 
59
 
# 16 bits unsigned integer header in native order representif the length of
60
 
# the following string. The string represents a '\n'-seperated tuple.
 
1
"""
 
2
This module implements a simple tuple transmission protocol. It's kept simple
 
3
to be implementable in other languages as well.
 
4
 
 
5
The protocol can only transmit lists of strings, which it splits up into chunks.
 
6
A chunk consists of a LENGTH byte, the actual PAYLOAD, and a STATUS byte.
 
7
 
 
8
A single string is split up into several chunks if it exceeds the maximum length
 
9
which can be specified by the LENGTH byte (255), otherwise a string is one
 
10
chunk.
 
11
 
 
12
The STATUS byte after every chunk tells if the chunk is
 
13
 
 
14
 - continued in the next chunk (CONT)
 
15
 - the last chunk of a string (NEXT)
 
16
 - the last chunk in the transmission (END)
 
17
 
 
18
In order to handle empty lists without getting too complicated, all lists are
 
19
extended by an arbitrary first element which just gets ignored.
 
20
 
 
21
 
 
22
Example:
 
23
 
 
24
  ["Hello", "World!"] is transmitted as:
 
25
 
 
26
  01  00 01   05   48 65 6C 6C 6F 01   06  57 6F 72 6C 64 21 02
 
27
 
 
28
  (1) ?  NEXT (5)  H  e  l  l  o  NEXT (6) W  o  r  l  d  !  END
 
29
"""
 
30
 
 
31
 
 
32
class XDRError(RuntimeError):
 
33
    pass
 
34
 
 
35
 
 
36
_SEND_ERROR = "--SEND ERROR--"
 
37
 
 
38
 
 
39
_CONT = chr(0)
 
40
_NEXT = chr(1)
 
41
_END  = chr(2)
61
42
 
62
43
 
63
44
def send(s, *args):
64
45
 
65
 
    """
66
 
    Writes data on a socket
67
 
 
68
 
    @param s: given socket
69
 
    @type  s: socket object
70
 
 
71
 
    @param *args: variable length arguments
72
 
    @type  *args: tuple
73
 
 
74
 
    NB: *args is a tuple and therefor a tuple is transmitted on the socket.
75
 
    That's why recv returns a tuple equals to args.
76
 
    """
77
 
 
78
 
    data = '\n'.join([ str(a).replace('\n', '\\n') for a in args ])
79
 
    assert len(data) != 0
80
 
    header = struct.pack(_HEADER_FORMAT, len(data))
81
 
 
82
 
    s.send(header)
83
 
    s.send(data)
84
 
 
 
46
    args = ["\0"] + list(args)
 
47
    while (args):
 
48
        a = args.pop(0)
 
49
 
 
50
        chunks = [ a[i:i + 0xff] for i in range(0, len(a), 0xff) ]
 
51
        while (chunks):
 
52
            c = chunks.pop(0)
 
53
            s.send(chr(len(c)))
 
54
            s.send(c)
 
55
            if (chunks): s.send(_CONT)
 
56
 
 
57
        if (args): s.send(_NEXT)
 
58
 
 
59
    s.send(_END)
 
60
 
 
61
 
 
62
def send_error(s):
 
63
 
 
64
    send(s, _SEND_ERROR)
85
65
 
86
66
 
87
67
def recv(s):
88
68
 
89
 
    """
90
 
    Reads data on a socket
91
 
 
92
 
    @param s: given socket
93
 
    @type  s: socket object
94
 
 
95
 
    @return : incoming data
96
 
    @rtype  : tuple
97
 
    """
98
 
 
99
 
    header = s.recv(_SIZEOF_HEADER)
100
 
 
101
 
    if not header:
102
 
        return
103
 
 
104
 
    size = struct.unpack(_HEADER_FORMAT, header)[0]
105
 
    data = s.recv(size)
106
 
 
107
 
    return tuple([ a.replace('\\n', '\n') for a in data.split('\n') ])
 
69
    args = []
 
70
    chunk = ""
 
71
    while (True):
 
72
        try:
 
73
            length = ord(s.recv(1))
 
74
        except:
 
75
            raise XDRError
 
76
 
 
77
        if (length): chunk += s.recv(length)
 
78
 
 
79
        flag = s.recv(1)
 
80
        if (flag == _CONT): continue
 
81
 
 
82
        args.append(chunk)
 
83
        chunk = ""
 
84
 
 
85
        if (flag == _END): break
 
86
    #end while
 
87
 
 
88
    return args[1:]