Project

General

Profile

RE: [Python] RPC connect - Errno 104 ยป htsp.py

HTSP python demo - Adam Sutton, 2012-08-07 17:21

 
1
#!/usr/bin/env python
2
#
3
# Really noddy script to connect to HTSP server
4
#
5

    
6
#
7
# translation of htsmsg_binary.c
8
#
9
# Note: source message should be a standard python types, dict, list, string
10
# and integer
11
#
12

    
13
HMF_MAP  = 1
14
HMF_S64  = 2
15
HMF_STR  = 3
16
HMF_BIN  = 4
17
HMF_LIST = 5
18

    
19
def hmf_type ( f ):
20
  if type(f) == list:
21
    return HMF_MAP
22
  elif type(f) == dict:
23
    return HMF_LIST
24
  elif type(f) == str:
25
    return HMF_STR
26
  elif type(f) == int:
27
    return HMF_S64
28
  else:
29
    raise Exception('invalid type')
30

    
31
def int2bin ( i ):
32
  return chr(i >> 24 & 0xFF) + chr(i >> 16 & 0xFF)\
33
       + chr(i >> 16 & 0xFF) + chr(i & 0xFF)
34

    
35
def bin2int ( d ):
36
  return (ord(d[0]) << 24) + (ord(d[1]) << 16)\
37
       + (ord(d[2]) <<  8) + ord(d[3])
38

    
39
def _htsmsg_binary_count ( f ):
40
  ret = 0
41
  if type(f) == str:
42
    ret = ret + len(f)
43
  elif type(f) == int:
44
    while (f):
45
      ret = ret + 1
46
      f   = f >> 8
47
  elif type(f) == list or type(f) == map:
48
    ret = ret + htsmsg_binary_count(f)
49
  else:
50
    raise Exception('invalid data type')
51
  return ret
52
  
53
def htsmsg_binary_count ( msg ):
54
  ret = 0
55
  lst = type(msg) == list
56
  for f in msg:
57
    ret = ret + 6
58
    if not lst: 
59
      ret = ret + len(f)
60
      f   = msg[f]
61
    ret = ret + _htsmsg_binary_count(f)
62
  return ret
63

    
64
def htsmsg_binary_write ( msg ):
65
  ret = ''
66
  lst = type(msg) == list
67
  for f in msg:
68
    na = ''
69
    if not lst:
70
      na = f
71
      f  = msg[f]
72
    ret = ret + chr(hmf_type(f))
73
    ret = ret + chr(len(na) & 0xFF)
74
    l   = _htsmsg_binary_count(f)
75
    ret = ret + int2bin(l)
76
    ret = ret + na
77

    
78
    if type(f) == list or type(f) == dict:
79
      ret = ret + htsmsg_binary_write(f)
80
    elif type(f) == str:
81
      ret = ret + f
82
    elif type(f) == int:
83
      while f:
84
        ret = ret + chr(f & 0xFF)
85
        f   = f >> 8
86
    else:
87
      raise Exception('invalid type')
88
  return ret
89

    
90
def htsmsg_binary_serialize ( msg ):
91
  cnt  = htsmsg_binary_count(msg)
92
  return int2bin(cnt) + htsmsg_binary_write(msg)
93

    
94
def htsmsg_binary_deserialize ( data ):
95
  msg = {}
96
  while len(data) > 5:
97
    typ  = ord(data[0])
98
    nlen = ord(data[1])
99
    dlen = bin2int(data[2:6])
100
    data = data[6:]
101

    
102
    if len < nlen + dlen: raise Exception('not enough data')
103
    
104
    name = data[:nlen]
105
    data = data[nlen:]
106
    if typ in [ HMF_STR, HMF_BIN ]:
107
      item = data[:dlen]
108
    elif typ == HMF_S64:
109
      item = 0
110
      i    = dlen - 1
111
      while i:
112
        item = (item << 8) | data[i]
113
    elif typ in [ HMF_LIST, HMF_MAP ]:
114
      item = htsmsg_binary_deserialize(data[:dlen])
115
    else:
116
      raise Exception('invalid data type %d' % typ)
117
    msg[name] = item
118
    data      = data[dlen:]
119
  return msg
120
  
121
def htsp_read ( s ):
122
  data = s.recv(4)
123
  if len(data) != 4: raise Exception('not enough data')
124
  num  = bin2int(data)
125
  print 'length = %d' %num
126
  data = s.recv(num)
127
  if len(data) != num: raise Exception('not enough data')
128
  # TODO: this should be done properly to handle partial read() calls
129
  return data
130

    
131
def htsp_method ( func, args ):
132
  args['method'] = func
133
  return htsmsg_binary_serialize(args)
134

    
135
#
136
# Test
137
#
138

    
139
if __name__ == '__main__':
140
  import socket, pprint
141
  s    = socket.create_connection(('localhost', 9982))
142
  helo = {
143
    'htspversion' : 5,
144
    'clientname'  : 'HTSP PyDemo'
145
  }
146
  data = htsp_method('hello', helo)
147
  s.send(data)
148
  data = htsp_read(s)
149
  print data
150
  msg  = htsmsg_binary_deserialize(data)
151
  pprint.pprint(msg)
    (1-1/1)