summaryrefslogtreecommitdiff
path: root/client.py
diff options
context:
space:
mode:
Diffstat (limited to 'client.py')
-rw-r--r--client.py116
1 files changed, 3 insertions, 113 deletions
diff --git a/client.py b/client.py
index dc9d796..aa164cb 100644
--- a/client.py
+++ b/client.py
@@ -1,8 +1,9 @@
-import struct
import socket
-
import logging
+import struct
+from structutil import (Struct, StructMeta, uint16, uint8, uint64,
+ uint32, uint32_arr, list_to_str)
import client_proto
logger = logging.getLogger('client')
@@ -31,112 +32,6 @@ SPICE_MAX_PASSWORD_LENGTH=60
SPICE_TICKET_KEY_PAIR_LENGTH=1024
SPICE_TICKET_PUBKEY_BYTES=(SPICE_TICKET_KEY_PAIR_LENGTH / 8 + 34)
-def unpack_list(structs, s):
- """ struct has a bug -
- sizeof('IBIII') == 20
- sizeof('IIIIB') == 16
- """
- ret = []
- start = 0
- for the_struct in structs:
- ret.extend(list(the_struct.unpack(s[start:start + s.size])))
- t += s.size
- return ret
-
-def group(format):
- return reduce(lambda cs, c: cs[:-1]+[cs[-1]+c] if len(cs) > 0 and c == cs[-1][-1] else cs+[c], format, [])
-
-class Elements(object):
- pass
-
-ENDIANESS = '<' # small endian
-
-class StructList(object):
-
- def __init__(self, formats):
- self._s = map(struct.Struct, (ENDIANESS+f for f in formats))
- self.size = sum([s.size for s in self._s])
-
- def pack(self, *args):
- i_s, i_e = 0, 0
- r = []
- for s in self._s:
- i_e += len(s.format) - (1 if s.format[0] in '<>' else 0)
- r.append(s.pack(*args[i_s:i_e]))
- i_s = i_e
- return ''.join(r)
-
- def unpack(self, st):
- r = []
- i_s, i_e = 0, 0
- for s in self._s:
- i_e += s.size
- r.append(list(s.unpack(st[i_s:i_e])))
- i_s = i_e
- return sum(r, [])
-
-class StructMeta(type):
- def __new__(meta, classname, bases, classDict):
- fields = classDict['fields']
- is_complex = classDict['_is_complex'] = callable(fields[-1][0])
- if is_complex:
- classDict['complex_field'] = complex_field = fields[-1]
- fields = fields[:-1]
- assert(not any(map(callable, fields)))
- classDict['_s'] = StructList(group(''.join(t for t,n in fields)))
- classDict['_names'] = [n for t,n in fields]
- classDict['size'] = classDict['_s'].size
- classDict['field_elements'] = [len(t) for t, n in fields]
- return type.__new__(meta, classname, bases, classDict)
-
-def indice_pairs(sizes):
- s = 0
- for size in sizes:
- yield s, s+size
- s += size
-
-def cut(elements, sizes):
- for s, e in indice_pairs(sizes):
- if e - s == 1:
- yield elements[s]
- else:
- yield elements[s:e]
-
-class Struct(object):
- @classmethod
- def parse(cls, s):
- base = list(cut(cls._s.unpack(s[:cls._s.size]), cls.field_elements))
- if cls._is_complex:
- import pdb; pdb.set_trace()
- return base
- return base
-
- @classmethod
- def make(cls, **kw):
- args = []
- args = [kw[n] for n in cls._names]
- assert(len(args) == len(cls._names) == len(kw))
- return cls._s.pack(*args)
-
- def __init__(self, *args, **kw):
- self.e = Elements()
- if (len(kw) == 0 and len(args) == 1) or (len(kw) == 1 and kw.has_key('s')):
- s = args[0] if len(args) == 1 else kw['s']
- self.elements = elements = self.parse(s)
- else:
- self.elements = elements = [kw[n] for n in self._names]
- self.e.__dict__.update(dict(zip(self._names, elements)))
-
- def tostr(self):
- return self.make(**self.e.__dict__)
-
-uint16 = 'H'
-uint32 = 'I'
-uint64 = 'Q'
-uint8 = 'B'
-
-uint32_arr = lambda s: ENDIANESS + uint32*s.e.size
-
class SpiceDataHeader(Struct):
__metaclass__ = StructMeta
fields = [(uint64, 'serial'), (uint16, 'type'), (uint32, 'size'),
@@ -240,11 +135,6 @@ def connect(host, port):
s.connect((host, port))
return s
-def list_to_str(l, type=uint32):
- if len(l) == 0:
- return ''
- return struct.pack(ENDIANESS+len(l)*type, l)
-
class Channel(object):
def __init__(self, s, connection_id, channel_type, channel_id,
common_caps, channel_caps):