changes to TvBus/metadata handling
[pyTivo/wgw.git] / beacon.py
blobead251655ff956cc1bbce03bd9f90263b2b9a4da
1 import re
2 import struct
3 from socket import *
4 from threading import Timer
5 import config
7 class Beacon:
9 UDPSock = socket(AF_INET, SOCK_DGRAM)
10 UDPSock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
11 services = []
13 def add_service(self, service):
14 self.services.append(service)
15 self.send_beacon()
17 def format_services(self):
18 return ';'.join(self.services)
20 def format_beacon(self, conntype, services=True):
21 beacon = []
23 guid = config.getGUID()
25 beacon.append('tivoconnect=1')
26 beacon.append('swversion=1')
27 beacon.append('method=%s' % conntype)
28 beacon.append('identity=%s' % guid)
30 beacon.append('machine=%s' % gethostname())
31 beacon.append('platform=pc')
32 if services:
33 beacon.append('services=' + self.format_services())
34 else:
35 beacon.append('services=TiVoMediaServer:0/http')
37 return '\n'.join(beacon)
39 def send_beacon(self):
40 beacon_ips = config.getBeaconAddresses()
41 for beacon_ip in beacon_ips.split():
42 if beacon_ip != 'listen':
43 try:
44 self.UDPSock.sendto(self.format_beacon('broadcast'),
45 (beacon_ip, 2190))
46 except error, e:
47 print e
49 def start(self):
50 self.send_beacon()
51 self.timer = Timer(60, self.start)
52 self.timer.start()
54 def stop(self):
55 self.timer.cancel()
57 def listen(self):
58 """ For the direct-connect, TCP-style beacon """
59 import thread
61 def server():
62 TCPSock = socket(AF_INET, SOCK_STREAM)
63 TCPSock.bind(('', 2190))
64 TCPSock.listen(5)
66 while True:
67 # Wait for a connection
68 client, address = TCPSock.accept()
70 # Accept the client's beacon
71 client_length = struct.unpack('!I', client.recv(4))[0]
72 client_message = client.recv(client_length)
74 # Send ours
75 message = self.format_beacon('connected')
76 client.send(struct.pack('!I', len(message)))
77 client.send(message)
78 client.close()
80 thread.start_new_thread(server, ())
82 def get_name(self, address):
83 """ Exchange beacons, and extract the machine name. """
84 our_beacon = self.format_beacon('connected', False)
85 machine_name = re.compile('machine=(.*)\n').search
87 try:
88 tsock = socket()
89 tsock.connect((address, 2190))
91 tsock.send(struct.pack('!I', len(our_beacon)))
92 tsock.send(our_beacon)
94 length = struct.unpack('!I', tsock.recv(4))[0]
95 tivo_beacon = tsock.recv(length)
97 tsock.close()
99 name = machine_name(tivo_beacon).groups()[0]
100 except:
101 name = address
103 return name
105 if __name__ == '__main__':
106 b = Beacon()
108 b.add_service('TiVoMediaServer:9032/http')
109 b.send_beacon()