Esempio n. 1
0
class Trans:
	# transaction types (i.e., reasons for making DHT requests)
	FINGER = 0 # finding finger peers for us (index = finger table index)
	BACKUP = 1 # finding redundant successors in case real one dies
	PRUNE = 2 # are we still in charge of this file? if not, drop it
	GET = 10 # finding place for client to get data (client = client socket)
	PUT = 11 # finding place for client to put data (client = client socket, data = file data))
	SHOW = 12 # transaction is asking for peer list (client = client socket, timer = 30sec timer)

	next = 0 # incrementing count of transactions

	def __init__(self, type, main, arg1=None, arg2=None):
		self.type = type
		self.main = main

		def make_trans():
			num = Trans.next
			Trans.next += 1
			return '%s-%d' % (main.myname, num)
		self.id = make_trans()

		if self.type == Trans.FINGER:
			self.index = arg1
		elif self.type == Trans.BACKUP:
			pass # nothing special to do
		elif self.type == Trans.PRUNE:
			pass # nothing special to do
		elif self.type == Trans.GET:
			self.client = arg1
		elif self.type == Trans.PUT:
			self.client = arg1
			self.data = arg2
		elif self.type == Trans.SHOW:
			self.client = arg1
			# create a timer; allow 30 seconds for a show to complete
			def cb():
				self.remove()
				# close client connection; we won't receive any more peer responses
				self.client.close_when_done()
			# we use a timeout to determine the roll call being done because
			# getting the SHOW message back doesn't mean we've seen all PEER messages
			self.timer = Timer(10, cb)
			self.timer.add()

	def add(self):
		self.main.trans[self.id] = self

	def remove(self):
		if self.type == Trans.SHOW:
			self.timer.remove()
		del self.main.trans[self.id]
Esempio n. 2
0
	def __init__(self, host, port, peers):
		self.host = host
		self.port = int(port)
		self.peers = {} # dictionary of Peer objects
		self.clients = set() # set of client sockets

		for i in peers:
			self.peers[i] = Peer(i)

		self.listen_sock = ListenSocket(self.port, self)

		self.keepalive_timer = Timer(15, self.keepalive_timer_cb)
		self.keepalive_timer.add()

		self.revive_timer = Timer(60, self.revive_timer_cb)
		self.revive_timer.add()
Esempio n. 3
0
	def __init__(self, type, main, arg1=None, arg2=None):
		self.type = type
		self.main = main

		def make_trans():
			num = Trans.next
			Trans.next += 1
			return '%s-%d' % (main.myname, num)
		self.id = make_trans()

		if self.type == Trans.FINGER:
			self.index = arg1
		elif self.type == Trans.BACKUP:
			pass # nothing special to do
		elif self.type == Trans.PRUNE:
			pass # nothing special to do
		elif self.type == Trans.GET:
			self.client = arg1
		elif self.type == Trans.PUT:
			self.client = arg1
			self.data = arg2
		elif self.type == Trans.SHOW:
			self.client = arg1
			# create a timer; allow 30 seconds for a show to complete
			def cb():
				self.remove()
				# close client connection; we won't receive any more peer responses
				self.client.close_when_done()
			# we use a timeout to determine the roll call being done because
			# getting the SHOW message back doesn't mean we've seen all PEER messages
			self.timer = Timer(10, cb)
			self.timer.add()
Esempio n. 4
0
	def revive_timer_cb(self):
		# re-add
		self.revive_timer = Timer(60, self.revive_timer_cb)
		self.revive_timer.add()

		for i in self.peers.values():
			if i.state == Peer.DEAD:
				self.do_spawn(i.host)
Esempio n. 5
0
	def keepalive_timer_cb(self):
		# re-add
		self.keepalive_timer = Timer(15, self.keepalive_timer_cb)
		self.keepalive_timer.add()

		for i in self.peers.values():
			if i.socket:
				i.socket.write([]) # send keepalive
Esempio n. 6
0
class Daemon:
	def __init__(self, host, port, peers):
		self.host = host
		self.port = int(port)
		self.peers = {} # dictionary of Peer objects
		self.clients = set() # set of client sockets

		for i in peers:
			self.peers[i] = Peer(i)

		self.listen_sock = ListenSocket(self.port, self)

		self.keepalive_timer = Timer(15, self.keepalive_timer_cb)
		self.keepalive_timer.add()

		self.revive_timer = Timer(60, self.revive_timer_cb)
		self.revive_timer.add()

	def run(self):
		Event.dispatch()

	def on_connect(self, socket):
		pass

	def on_error(self, socket):
		# see if it's a peer; if it's a client, remove socket
		for p in self.peers.values():
			if p.socket == socket:
				p.disconnected()
				self.broadcast(p.get_state())
		self.clients.discard(socket) # just in case

	def on_data(self, socket, data):
		pos = data.find('\n')
		if pos < 0: # need to wait for new line
			return 0
		elif pos == 0:
			return 1 # just a keep-alive

		args = data[0:pos].split(' ')

		# possible messages (peer)
		# HELLO host -- peer is now active and ready to be started
		# STARTED host port -- peer is active and listening on given port
		# STOPPED host -- peer is stopped
		if args[0] == 'HELLO' and len(args) == 2:
			host = args[1]
			peer = self.peers[host]
			peer.hello(socket)
			self.broadcast(peer.get_state())
		elif args[0] == 'STARTED' and len(args) == 3:
			host = args[1]
			port = args[2]
			peer = self.peers[host]
			peer.started(port)
			self.broadcast(peer.get_state())
		elif args[0] == 'STOPPED' and len(args) == 2:
			host = args[1]
			peer = self.peers[host]
			peer.stopped()
			self.broadcast(peer.get_state())
		# possible messages (client)
		# CHELLO -- client is connected and would like status
		# CSTART host -- request to start host
		# CSTOP host -- request to stop host
		# CKILL host -- request to kill host
		elif args[0] == 'CHELLO' and len(args) == 1:
			for i in self.peers.values():
				socket.write(i.get_state())
			self.clients.add(socket)
		elif args[0] == 'CSTART' and len(args) == 2:
			self.do_start(args[1])
		elif args[0] == 'CSTOP' and len(args) == 2:
			self.do_stop(args[1])
		elif args[0] == 'CKILL' and len(args) == 2:
			self.do_kill(args[1])
		else:
			print 'unknown message:', ' '.join(args)

		return pos + 1

	def do_start(self, host):
		peer = self.peers[host]
		try:
			bootstrap = random.choice(['%s:%d' % (i.host,i.port) for i in self.peers.values() if i.state == Peer.STARTED])
		except IndexError:
			bootstrap = 'none'
		if peer.state == Peer.STOPPED:
			peer.socket.write(['START', bootstrap])

	def do_stop(self, host):
		peer = self.peers[host]
		if peer.state == Peer.STARTED:
			peer.socket.write(['STOP'])

	def do_kill(self, host):
		peer = self.peers[host]
		if peer.state == Peer.STARTED or peer.state == Peer.STOPPED:
			peer.socket.write(['KILL'])

	def broadcast(self, msg):
		for i in self.clients:
			i.write(msg)

	# send out a newline sometimes
	def keepalive_timer_cb(self):
		# re-add
		self.keepalive_timer = Timer(15, self.keepalive_timer_cb)
		self.keepalive_timer.add()

		for i in self.peers.values():
			if i.socket:
				i.socket.write([]) # send keepalive

	def revive_timer_cb(self):
		# re-add
		self.revive_timer = Timer(60, self.revive_timer_cb)
		self.revive_timer.add()

		for i in self.peers.values():
			if i.state == Peer.DEAD:
				self.do_spawn(i.host)

	def do_spawn(self, host):
		# spawn shell script that delivers payload
		Popen(['./deliver.sh', host, '%s:%d' % (self.host, self.port)])