diff options
Diffstat (limited to 'client.py')
| -rw-r--r-- | client.py | 116 |
1 files changed, 3 insertions, 113 deletions
@@ -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): |
