def _client_respond(self, client, their_ts): l = protocol.PTP(data=[]) l.data = [] t = protocol.TLV(type=protocol.PTP_TYPE_SERVERVER, data=protocol.UInt(size=1, data=PTP_SERVERVER)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_SEQUENCE, data=protocol.UInt(size=4, data=self.server_seq)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_UUID, data=protocol.String(data=client['uuid'])) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_YOURTS, data=protocol.UInt(size=8, data=their_ts)) l.data.append(t) packet = l.pack() if len(packet) > protocol.PTP_MTU: # bad self.ui.log("Ignoring attempt to send ts %d bytes to client %s. MTU is %d" % \ (len(packet), str(client['sin']), protocol.PTP_MTU)) return if self.args.debug: self.ui.log("Sending ts %d bytes to client %s" % (len(packet), str(client['sin']))) self.ui.log("%s" % repr(protocol.PTP(packet)), indent=' ') if self.args.hexdump: self.ui.log(hexdump.hexdump(result='return', data=packet)) self.sock.sendto(packet, client['sin']) self.server_seq += 1L
def _server_beacons(self, shutdown=False): # Tell the server about ourself l = protocol.PTP(data=[]) l.data = [] t = protocol.TLV(type=protocol.PTP_TYPE_CLIENTVER, data=protocol.UInt(size=1, data=PTP_CLIENTVER)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_SEQUENCE, data=protocol.UInt(size=4, data=self.server_seq)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_UUID, data=protocol.String(data=self.uuid)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_PTPADDR, data=protocol.Address(data=(self.addr, self.port))) l.data.append(t) if shutdown: t = protocol.TLV(type=protocol.PTP_TYPE_SHUTDOWN, data=protocol.UInt(size=1, data=1)) l.data.append(t) else: t = protocol.TLV(type=protocol.PTP_TYPE_MYTS, data=protocol.UInt(size=8, data=int(time.time() * 2**32))) l.data.append(t) tmp = copy.deepcopy(self.servers) for k in tmp: if 'uuid' in tmp[k]: del (tmp[k]['uuid']) t = protocol.TLV(type=protocol.PTP_TYPE_META, data=protocol.JSON(data=tmp)) l.data.append(t) packet = l.pack() if len(packet) > protocol.PTP_MTU: # bad self.ui.log( "Ignoring attempt to send %d bytes to servers. MTU is %d" % (len(packet), protocol.PTP_MTU)) return if self.args.debug: self.ui.log("Sending %d bytes to servers:" % len(packet)) self.ui.log("%s" % repr(protocol.PTP(packet)), indent=' ') if self.args.hexdump: self.ui.log(hexdump.hexdump(result='return', data=packet)) with self._slock: for k in self.servers: server = self.servers[k] server['stats']['sent'] += 1 self.sock.sendto(packet, server['sin']) self.ui.peer_update('server', server['sin'], server['stats']) self.server_seq += 1L
def _client_beacon(self, k, client): # We need a list of TLVs and then form a PTP fron them l = protocol.PTP(data=[]) l.data = [] t = protocol.TLV(type=protocol.PTP_TYPE_SERVERVER, data=protocol.UInt(size=1, data=PTP_SERVERVER)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_SEQUENCE, data=protocol.UInt(size=4, data=self.server_seq)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_UUID, data=protocol.String(data=client['uuid'])) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_MYTS, data=protocol.UInt(size=8, data=int(time.time()*2**32))) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_YOURADDR, data=protocol.Address(data=client['sin'])) l.data.append(t) # Now add the list of known clients count = 0 for sk in self.clients: if sk == k: continue # skip the client we're sending this to sc = self.clients[sk] t = protocol.TLV(type=protocol.PTP_TYPE_CLIENTLIST_EXT, data=protocol.Address(data=sc['sin'])) l.data.append(t) count += 1 # If this client address matches the address we're sending this packet to then we # also send its local address - the clients can then try to talk locally if sc['sin'][0] == client['sin'][0]: t = protocol.TLV(type=protocol.PTP_TYPE_CLIENTLIST_INT, data=protocol.Address(data=sc['ptpaddr'])) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_CLIENTLEN, data=protocol.UInt(size=1, data=count)) l.data.append(t) packet = l.pack() if len(packet) > protocol.PTP_MTU: # bad self.ui.log("Ignoring attempt to send %d bytes to client %s. MTU is %d" % \ (len(packet), str(client['sin']), protocol.PTP_MTU)) return if self.args.debug: self.ui.log("Sending %d bytes to client %s" % (len(packet), str(client['sin']))) self.ui.log("%s" % repr(protocol.PTP(packet)), indent=' ') if self.args.hexdump: self.ui.log(hexdump.hexdump(result='return', data=packet)) self.sock.sendto(packet, client['sin']) client['stats']['sent'] += 1 self.server_seq += 1L self.ui.peer_update('client', client['sin'], client['stats'])
def _client_parse(self, buf, sin, client): l = protocol.PTP(buf) if l is None: self.ui.log("Client packet from %s failed to parse!" % repr(sin)) return False if l.buf_csum is None or l.buf_csum != l.csum: self.ui.log("Client packet from %s has a bad checksum!" % repr(sin)) return False client['ts'] = time.time() client['stats']['rcvd'] += 1 if self.args.debug: self.ui.log(repr(l)) for tlv in l.data: p = tlv.data if p.ptp_type == protocol.PTP_TYPE_CLIENTVER: client['clientver'] = p.data elif p.ptp_type == protocol.PTP_TYPE_SEQUENCE: client['sequence'] = p.data elif p.ptp_type == protocol.PTP_TYPE_UUID: client['uuid'] = p.data elif p.ptp_type == protocol.PTP_TYPE_MYTS: self._client_respond(client, p.data) client['myts'] = float(p.data) / float(2**32) elif p.ptp_type == protocol.PTP_TYPE_YOURTS: ts = float(p.data) / float(2**32) rtt = client['ts'] - ts client['stats']['rtt'] = rtt client['stats']['ackd'] += 1 self.ui.log("ACK from client %s; RTT %fs" % (str(sin), rtt)) self.ui.peer_update('client', client['sin'], client['stats']) return True
def _client_beacons(self): with self._clock: for k in self.clients: client = self.clients[k] if not 'myseq' in client or not 'sin' in client: continue if 'uuid' in client and client['uuid'] == self.uuid: continue # self! l = protocol.PTP(data=[]) l.data = [] t = protocol.TLV(type=protocol.PTP_TYPE_CLIENTVER, data=protocol.UInt(size=1, data=PTP_CLIENTVER)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_SEQUENCE, data=protocol.UInt(size=4, data=client['myseq'])) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_UUID, data=protocol.String(data=self.uuid)) l.data.append(t) t = protocol.TLV(type=protocol.PTP_TYPE_MYTS, data=protocol.UInt(size=8, data=int(time.time() * 2**32))) l.data.append(t) packet = l.pack() if len(packet) > protocol.PTP_MTU: # bad self.ui.log("Ignoring attempt to send ts %d bytes to client %s. MTU is %d" % \ (len(packet), str(client['sin']), protocol.PTP_MTU)) return if self.args.debug: self.ui.log("Sending ts %d bytes to client %s" % (len(packet), str(client['sin']))) self.ui.log("%s" % repr(protocol.PTP(packet)), indent=' ') if self.args.hexdump: self.ui.log( hexdump.hexdump(result='return', data=packet)) self.sock.sendto(packet, client['sin']) client['stats']['sent'] += 1 client['myseq'] += 1 self.ui.peer_update('client', client['sin'], client['stats'])
def _server_parse(self, buf, sin, server): l = protocol.PTP(buf) if l is None: self.ui.log("Server packet from %s failed to parse!" % repr(sin)) return False if l.buf_csum is None or l.buf_csum != l.csum: self.ui.log("Server packet from %s has a bad checksum!" % repr(sin)) return False server['ts'] = time.time() server['stats']['rcvd'] += 1 if self.args.debug: self.ui.log(repr(l)) new_clients = [] num_clients = None for tlv in l.data: p = tlv.data if p.ptp_type == protocol.PTP_TYPE_SERVERVER: server['serverver'] = p.data elif p.ptp_type == protocol.PTP_TYPE_SEQUENCE: server['sequence'] = p.data elif p.ptp_type == protocol.PTP_TYPE_UUID: server['uuid'] = p.data elif p.ptp_type == protocol.PTP_TYPE_MYTS: self._server_respond(server, p.data) server['myts'] = float(p.data) / float(2**32) elif p.ptp_type == protocol.PTP_TYPE_YOURTS: ts = float(p.data) / float(2**32) rtt = server['ts'] - ts server['stats']['rtt'] = rtt server['stats']['ackd'] += 1 self.ui.log("ACK from server %s; RTT %fs" % (str(sin), rtt)) elif p.ptp_type == protocol.PTP_TYPE_CLIENTLEN: num_clients = p.data elif p.ptp_type == protocol.PTP_TYPE_CLIENTLIST_EXT: new_clients.append(p.data) # should be a sockaddr elif p.ptp_type == protocol.PTP_TYPE_CLIENTLIST_INT: # server thinks the previous address may be on the same # network as us, so has sent us a clients internal address # This is crude, but we just overwrite the previous address for now new_clients[-1] = p.data elif p.ptp_type == protocol.PTP_TYPE_YOURADDR: self.ui.log("Server sees us as %s" % repr(p.data)) self.ui.set_address(p.data[0], p.data[1]) self.ui.peer_update('server', server['sin'], server['stats']) if num_clients is not None: if num_clients == len(new_clients): with self._clock: # Sync the client list delete = [] for k in self.clients: if not self.clients[k]['sin'] in new_clients: # old delete.append(k) for k in delete: if self.args.debug: self.ui.log("Removing old client %s" % str(self.clients[k]['sin'])) self.ui.peer_del(group='client', sin=self.clients[k]['sin']) del (self.clients[k]) for sin in new_clients: k = _mkey(sin[0], sin[1]) if k not in self.clients: # new if self.args.debug: self.ui.log("Adding new client %s" % str(sin)) self.clients[k] = { 'sin': sin, 'ts': time.time(), 'myseq': 0L, 'stats': { 'sent': 0, 'rcvd': 0, 'ackd': 0, 'rtt': 0, }, } self.ui.peer_add(group='client', sin=sin) if self.args.debug: self.ui.log("Client count: %d" % len(self.clients))