Did something, apparently
[progcomp2013.git] / qchess / src / network.py
1 import socket
2 import select
3
4 network_timeout_start = -1.0 # Timeout in seconds to wait for the start of a message
5 network_timeout_delay = 1.0 # Maximum time between two characters being received
6
7 class Network():
8         def __init__(self, colour, address = None):
9                 self.socket = socket.socket()
10                 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
11                 #self.socket.setblocking(0)
12                 
13                 self.server = (address == None)
14
15                 if colour == "white":
16                         self.port = 4562
17                 else:
18                         self.port = 4563
19
20                 self.src = None
21
22         #       print str(self) + " listens on port " + str(self.port)
23
24                 if address == None:
25                         self.host = "0.0.0.0" #socket.gethostname() # Breaks things???
26                         self.socket.bind((self.host, self.port))
27                         self.socket.listen(5)   
28
29                         self.src, self.address = self.socket.accept()
30                         self.src.send("ok\n")
31                         if self.get_response() == "QUIT":
32                                 self.src.close()
33                 else:
34                         self.host = address
35                         self.socket.connect((address, self.port))
36                         self.src = self.socket
37                         self.src.send("ok\n")
38                         if self.get_response() == "QUIT":
39                                 self.src.close()
40                         self.address = (address, self.port)
41
42         def get_response(self):
43                 # Timeout the start of the message (first character)
44                 if network_timeout_start > 0.0:
45                         ready = select.select([self.src], [], [], network_timeout_start)[0]
46                 else:
47                         ready = [self.src]
48                 if self.src in ready:
49                         s = self.src.recv(1)
50                 else:
51                         raise Exception("UNRESPONSIVE")
52
53
54                 while s[len(s)-1] != '\n':
55                         # Timeout on each character in the message
56                         if network_timeout_delay > 0.0:
57                                 ready = select.select([self.src], [], [], network_timeout_delay)[0]
58                         else:
59                                 ready = [self.src]
60                         if self.src in ready:
61                                 s += self.src.recv(1) 
62                         else:
63                                 raise Exception("UNRESPONSIVE")
64
65                 return s.strip(" \r\n")
66
67         def send_message(self,s):
68                 if network_timeout_start > 0.0:
69                         ready = select.select([], [self.src], [], network_timeout_start)[1]
70                 else:
71                         ready = [self.src]
72
73                 if self.src in ready:
74                         self.src.send(s + "\n")
75                 else:
76                         raise Exception("UNRESPONSIVE")
77
78         def check_quit(self, s):
79                 s = s.split(" ")
80                 if s[0] == "QUIT":
81                         with game.lock:
82                                 game.final_result = " ".join(s[1:]) + " " + str(opponent(self.colour))
83                         game.stop()
84                         return True
85
86
87                 
88
89 class NetworkSender(Player,Network):
90         def __init__(self, base_player, address = None):
91                 self.base_player = base_player
92                 Player.__init__(self, base_player.name, base_player.colour)
93
94                 self.address = address
95
96         def connect(self):
97                 nAttempts=3
98                 for i in range(nAttempts):
99                         try:
100                                 Network.__init__(self, self.colour, self.address)
101                                 debug(str(self) +" connected to " + str(self.address))
102                                 return
103                         except Exception, e:
104                                 debug(str(self) +" attempt " + str(i) + ": " +  str(e.message))
105                                 
106                 raise Exception("NETWORK - Can't connect to " + str(self.address))
107
108
109         def select(self):
110                 [x,y] = self.base_player.select()
111                 choice = self.board.grid[x][y]
112                 s = str(x) + " " + str(y)
113                 #debug(str(self) + " sends: " + str(s))
114                 self.send_message(s)
115                 return [x,y]
116
117         def get_move(self):
118                 [x,y] = self.base_player.get_move()
119                 s = str(x) + " " + str(y)
120                 #debug(str(self) + " sends: " + str(s))
121                 self.send_message(s)
122                 return [x,y]
123
124         def update(self, s):
125                 
126                 self.base_player.update(s)
127                 if self.server == True:
128                         #debug(str(self) + " sends: " + str(s))
129                         self.send_message(s)
130                 return s
131                 
132                 s = s.split(" ")
133                 [x,y] = map(int, s[0:2])
134                 selected = self.board.grid[x][y]
135                 if selected != None and selected.colour == self.colour and len(s) > 2 and not "->" in s:
136                         s = " ".join(s[0:3])
137                         for i in range(2):
138                                 if selected.types[i][0] != '?':
139                                         s += " " + str(selected.types[i])
140                                 else:
141                                         s += " unknown"
142                         #debug(str(self) +" sending: " + str(s))
143                         self.send_message(s)
144                                 
145
146         def quit(self, final_result):
147                 self.base_player.quit(final_result)
148                 #self.src.send("QUIT " + str(final_result) + "\n")
149                 self.src.close()
150                 
151         def __str__(self):
152                 s = "NetworkSender:"
153                 if self.server:
154                         s += "server"
155                 else:
156                         s += "client"
157                 s += ":"+str(self.address)
158                 return s
159
160
161 class NetworkReceiver(Player,Network):
162         def __init__(self, colour, address=None):
163                 
164                 s = "@network"
165                 if address != None:
166                         s += ":"+str(address)
167                 Player.__init__(self, s, colour)
168
169                 self.address = address
170
171                 self.board = None
172
173
174         def connect(self):
175                 nAttempts=3
176                 for i in range(nAttempts):
177                         try:
178                                 Network.__init__(self, self.colour, self.address)
179                                 debug(str(self) +" connected to " + str(self.address))
180                                 return
181                         except Exception, e:
182                                 debug(str(self) +" attempt " + str(i) + ": " +  str(e.message))
183                                 
184                 raise Exception("NETWORK - Can't connect to " + str(self.address))
185                         
186                         
187
188         def select(self):
189                 
190                 s = self.get_response()
191                 #debug(str(self) +".select reads: " + str(s))
192                 [x,y] = map(int,s.split(" "))
193                 if x == -1 and y == -1:
194                         #print str(self) + ".select quits the game"
195                         with game.lock:
196                                 game.final_state = "network terminated " + self.colour
197                         game.stop()
198                 return [x,y]
199         def get_move(self):
200                 s = self.get_response()
201                 #debug(str(self) +".get_move reads: " + str(s))
202                 [x,y] = map(int,s.split(" "))
203                 if x == -1 and y == -1:
204                         #print str(self) + ".get_move quits the game"
205                         with game.lock:
206                                 game.final_state = "network terminated " + self.colour
207                         game.stop()
208                 return [x,y]
209
210         def update(self, result):
211                 if self.server == True:
212                         return result
213                 s = self.get_response()
214                 #debug(str(self) + ".update reads: " + str(s))
215                 if not "->" in s.split(" "):
216                         self.board.update(s, sanity=False)
217                 return s
218                 
219
220         def quit(self, final_result):
221                 self.src.close()
222                 
223         def __str__(self):
224                 s = "NetworkReceiver:"
225                 if self.server:
226                         s += "server"
227                 else:
228                         s += "client"
229                 s += ":"+str(self.address)
230                 return s
231         

UCC git Repository :: git.ucc.asn.au