32a7b503a9720632f2ceee4c836ccec53293ffd5
[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 NetworkPlayer(Player):
8         def __init__(self, colour, network, player):
9                 Player.__init__(self, "@network:"+str(network.address), colour) 
10                 self.player = player
11                 self.network = network
12                 
13         def __str__(self):
14                 return "NetworkPlayer<"+str(self.colour)+","+str(self.player)+">"
15                 
16         def select(self):
17                 debug(str(self) + " select called")
18                 if self.player != None:
19                         s = self.player.select()
20                         self.send_message(str(s[0]) + " " + str(s[1]))
21                 else:
22                         s = map(int, self.get_response().split(" "))
23                         for p in game.players:
24                                 if p != self and isinstance(p, NetworkPlayer) and p.player == None:
25                                         p.network.send_message(str(s[0]) + " " + str(s[1]))
26                 return s
27         
28         def send_message(self, message):
29                 debug(str(self) + " send_message(\""+str(message)+"\") called")
30                 self.network.send_message(message)
31                 
32         def get_response(self):
33                 debug(str(self) + " get_response() called")
34                 s = self.network.get_response()
35                 debug(str(self) + " get_response() returns \""+str(s)+"\"")
36                 return s
37                         
38                         
39         def get_move(self):
40                 debug(str(self) + " get_move called")
41                 if self.player != None:
42                         s = self.player.get_move()
43                         self.send_message(str(s[0]) + " " + str(s[1]))
44                 else:
45                         s = map(int, self.get_response().split(" "))
46                         for p in game.players:
47                                 if p != self and isinstance(p, NetworkPlayer) and p.player == None:
48                                         p.network.send_message(str(s[0]) + " " + str(s[1]))
49                 return s
50         
51         def update(self, result):
52                 debug(str(self) + " update(\""+str(result)+"\") called")
53                 if self.network.server == True:
54                         if self.player == None:
55                                 self.send_message(result)
56                 elif self.player != None:
57                         result = self.get_response()
58                         self.board.update(result, deselect=False)
59                 
60                 
61                 
62                 if self.player != None:
63                         result = self.player.update(result)
64                         
65                 return result
66                 
67                 
68         
69         def base_player(self):
70                 if self.player == None:
71                         return self
72                 else:
73                         return self.player.base_player()
74                 
75         def quit(self, result):
76                 pass
77
78 class Network():
79         def __init__(self, address = (None,4562)):
80                 self.socket = socket.socket()
81                 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
82                 #self.socket.setblocking(0)
83                 self.address = address
84                 self.server = (address[0] == None)
85                 
86                 
87                 self.connected = False
88                         
89         def connect(self):      
90                 debug(str(self) + "Tries to connect")
91                 self.connected = True
92                 if self.address[0] == None:
93                         self.host = "0.0.0.0" #socket.gethostname() # Breaks things???
94                         self.socket.bind((self.host, self.address[1]))
95                         self.socket.listen(5)   
96
97                         self.src, self.actual_address = self.socket.accept()
98                         
99                         self.src.send("ok\n")
100                         s = self.get_response()
101                         if s == "QUIT":
102                                 self.src.close()
103                                 return
104                         elif s != "ok":
105                                 self.src.close()
106                                 self.__init__(colour, (self.address[0], int(s)), baseplayer)
107                                 return
108                         
109                 else:
110                         time.sleep(0.3)
111                         self.socket.connect(self.address)
112                         self.src = self.socket
113                         self.src.send("ok\n")
114                         s = self.get_response()
115                         if s == "QUIT":
116                                 self.src.close()
117                                 return
118                         elif s != "ok":
119                                 self.src.close()
120                                 self.__init__(colour, (self.address[0], int(s)), baseplayer)
121                                 return
122                         
123
124                 
125         def __str__(self):
126                 return "@network:"+str(self.address)
127
128         def get_response(self):
129                 
130                 # Timeout the start of the message (first character)
131                 if network_timeout_start > 0.0:
132                         ready = select.select([self.src], [], [], network_timeout_start)[0]
133                 else:
134                         ready = [self.src]
135                 if self.src in ready:
136                         s = self.src.recv(1)
137                 else:
138                         raise Exception("UNRESPONSIVE")
139
140
141                 while s[len(s)-1] != '\n':
142                         # Timeout on each character in the message
143                         if network_timeout_delay > 0.0:
144                                 ready = select.select([self.src], [], [], network_timeout_delay)[0]
145                         else:
146                                 ready = [self.src]
147                         if self.src in ready:
148                                 s += self.src.recv(1) 
149                         else:
150                                 raise Exception("UNRESPONSIVE")
151
152                 
153                 return s.strip(" \r\n")
154
155         def send_message(self,s):
156                 if network_timeout_start > 0.0:
157                         ready = select.select([], [self.src], [], network_timeout_start)[1]
158                 else:
159                         ready = [self.src]
160
161                 if self.src in ready:
162                         self.src.send(s + "\n")
163                 else:
164                         raise Exception("UNRESPONSIVE")
165                 
166                 
167
168         def close(self):
169                 self.src.shutdown()
170                 self.src.close()

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