network.py 3.76 KB
Newer Older
Sam Moore's avatar
Sam Moore committed
1
import socket
Sam Moore's avatar
Sam Moore committed
2 3 4 5
import select

network_timeout_start = -1.0 # Timeout in seconds to wait for the start of a message
network_timeout_delay = 1.0 # Maximum time between two characters being received
Sam Moore's avatar
Sam Moore committed
6

Sam Moore's avatar
Sam Moore committed
7 8 9 10 11 12 13 14 15 16 17 18 19
class Network(Player):
	def __init__(self, colour, address = (None,4562), baseplayer = None):
		
		if baseplayer != None:
			name = baseplayer.name + " --> @network"
		else:
			name = "<-- @network"
		
		
				
		Player.__init__(self, name, colour)
		debug("Colour is " + str(self.colour))
		
Sam Moore's avatar
Sam Moore committed
20
		self.socket = socket.socket()
Sam Moore's avatar
Sam Moore committed
21
		self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Sam Moore's avatar
Sam Moore committed
22
		self.baseplayer = baseplayer
Sam Moore's avatar
Sam Moore committed
23
		#self.socket.setblocking(0)
Sam Moore's avatar
Sam Moore committed
24
		
Sam Moore's avatar
Sam Moore committed
25 26
		self.address = address
		self.server = (address[0] == None)
Sam Moore's avatar
Sam Moore committed
27

Sam Moore's avatar
Sam Moore committed
28 29 30 31 32 33 34 35 36 37
		if self.colour == "black":
			self.address = (self.address[0], self.address[1] + 1)
				
		debug(str(self) + ":"+str(self.address))
		
		self.board = None
			
			
	def connect(self):	
		if self.address[0] == None:
Sam Moore's avatar
Sam Moore committed
38
			self.host = "0.0.0.0" #socket.gethostname() # Breaks things???
Sam Moore's avatar
Sam Moore committed
39
			self.socket.bind((self.host, self.address[1]))
Sam Moore's avatar
Sam Moore committed
40 41
			self.socket.listen(5)	

Sam Moore's avatar
Sam Moore committed
42 43
			self.src, self.actual_address = self.socket.accept()
			
Sam Moore's avatar
Sam Moore committed
44
			self.src.send("ok\n")
Sam Moore's avatar
Sam Moore committed
45 46
			s = self.get_response()
			if s == "QUIT":
Sam Moore's avatar
Sam Moore committed
47
				self.src.close()
Sam Moore's avatar
Sam Moore committed
48 49 50 51 52 53
				return
			elif s != "ok":
				self.src.close()
				self.__init__(colour, (self.address[0], int(s)), baseplayer)
				return
			
Sam Moore's avatar
Sam Moore committed
54
		else:
Sam Moore's avatar
Sam Moore committed
55
			self.socket.connect(self.address)
Sam Moore's avatar
Sam Moore committed
56
			self.src = self.socket
Sam Moore's avatar
Sam Moore committed
57
			self.src.send("ok\n")
Sam Moore's avatar
Sam Moore committed
58 59 60 61 62
			s = self.get_response()
			if s == "QUIT":
				self.src.close()
				return
			elif s != "ok":
Sam Moore's avatar
Sam Moore committed
63
				self.src.close()
Sam Moore's avatar
Sam Moore committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
				self.__init__(colour, (self.address[0], int(s)), baseplayer)
				return
			

	def select(self):
		if self.baseplayer != None:
			s = self.baseplayer.select()
			self.send_message(str(s[0]) + " " + str(s[1]))
			return s
		return map(int,self.get_response().split(" "))
	
	def get_move(self):
		if self.baseplayer != None:
			s = self.baseplayer.get_move()
			self.send_message(str(s[0]) + " " + str(s[1]))
			return s
		return map(int,self.get_response().split(" "))
	
	def update(self, result):
		if self.baseplayer != None:
			result = self.baseplayer.update(result)
			self.send_message(result)
			return result
		if self.server:
			self.send_message(result)
		else:
			s = self.get_response()
			if self.board != None:
				self.board.update(s)
			
	def __str__(self):
		return "Network<"+str(self.colour)+","+str(self.baseplayer)+">:"+str(self.address)
Sam Moore's avatar
Sam Moore committed
96 97

	def get_response(self):
Sam Moore's avatar
Sam Moore committed
98
		debug(str(self) + " get_response called...")
Sam Moore's avatar
Sam Moore committed
99 100 101 102 103 104 105 106 107 108
		# Timeout the start of the message (first character)
		if network_timeout_start > 0.0:
			ready = select.select([self.src], [], [], network_timeout_start)[0]
		else:
			ready = [self.src]
		if self.src in ready:
			s = self.src.recv(1)
		else:
			raise Exception("UNRESPONSIVE")

Sam Moore's avatar
Sam Moore committed
109 110

		while s[len(s)-1] != '\n':
Sam Moore's avatar
Sam Moore committed
111 112 113 114 115 116 117 118 119 120
			# Timeout on each character in the message
			if network_timeout_delay > 0.0:
				ready = select.select([self.src], [], [], network_timeout_delay)[0]
			else:
				ready = [self.src]
			if self.src in ready:
				s += self.src.recv(1) 
			else:
				raise Exception("UNRESPONSIVE")

Sam Moore's avatar
Sam Moore committed
121
		debug(str(self) + " get_response returns " + s.strip(" \r\n"))
Sam Moore's avatar
Sam Moore committed
122 123 124 125 126 127 128 129 130 131 132 133
		return s.strip(" \r\n")

	def send_message(self,s):
		if network_timeout_start > 0.0:
			ready = select.select([], [self.src], [], network_timeout_start)[1]
		else:
			ready = [self.src]

		if self.src in ready:
			self.src.send(s + "\n")
		else:
			raise Exception("UNRESPONSIVE")
Sam Moore's avatar
Sam Moore committed
134 135
		
		debug(str(self) + " send_message sent " + s)
Sam Moore's avatar
Sam Moore committed
136 137 138 139 140 141 142 143

	def check_quit(self, s):
		s = s.split(" ")
		if s[0] == "QUIT":
			with game.lock:
				game.final_result = " ".join(s[1:]) + " " + str(opponent(self.colour))
			game.stop()
			return True
Sam Moore's avatar
Sam Moore committed
144
			
Sam Moore's avatar
Sam Moore committed
145 146 147
	def quit(self, result):
		if self.baseplayer != None:
			self.send_message("QUIT")
Sam Moore's avatar
Sam Moore committed
148
			
Sam Moore's avatar
Sam Moore committed
149 150 151 152
		with game.lock:
			game.final_result = result
		game.stop()	

Sam Moore's avatar
Sam Moore committed
153 154 155



Sam Moore's avatar
Sam Moore committed
156