Cooperation/CooperationClient.py

changeset 1221
291dc0a51947
parent 1131
7781e396c903
child 1509
c0b5e693b0eb
equal deleted inserted replaced
1219:c051673f8aaf 1221:291dc0a51947
8 """ 8 """
9 9
10 import collections 10 import collections
11 11
12 from PyQt4.QtCore import QObject, pyqtSignal, QProcess, QRegExp 12 from PyQt4.QtCore import QObject, pyqtSignal, QProcess, QRegExp
13 from PyQt4.QtNetwork import QHostInfo, QHostAddress, QAbstractSocket 13 from PyQt4.QtNetwork import QHostInfo, QHostAddress, QAbstractSocket, QNetworkInterface
14 14
15 from .CooperationServer import CooperationServer 15 from .CooperationServer import CooperationServer
16 from .Connection import Connection 16 from .Connection import Connection
17 17
18 import Preferences 18 import Preferences
44 44
45 @param parent reference to the parent object (QObject) 45 @param parent reference to the parent object (QObject)
46 """ 46 """
47 super().__init__(parent) 47 super().__init__(parent)
48 48
49 self.__server = CooperationServer(self) 49 self.__chatWidget = parent
50
51 self.__servers = []
52 for networkInterface in QNetworkInterface.allInterfaces():
53 for addressEntry in networkInterface.addressEntries():
54 address = addressEntry.ip()
55 # fix scope of link local addresses
56 if address.toString().lower().startswith("fe80"):
57 address.setScopeId(networkInterface.humanReadableName())
58 server = CooperationServer(address, self)
59 server.newConnection.connect(self.__newConnection)
60 self.__servers.append(server)
61
50 self.__peers = collections.defaultdict(list) 62 self.__peers = collections.defaultdict(list)
51 63
52 self.__initialConnection = None 64 self.__initialConnection = None
53 65
54 envVariables = ["USERNAME.*", "USER.*", "USERDOMAIN.*", 66 envVariables = ["USERNAME.*", "USER.*", "USERDOMAIN.*",
68 break 80 break
69 81
70 if self.__username == "": 82 if self.__username == "":
71 self.__username = self.trUtf8("unknown") 83 self.__username = self.trUtf8("unknown")
72 84
73 self.__server.newConnection.connect(self.__newConnection) 85 self.__listening = False
74 86 self.__serversErrorString = ""
75 def server(self): 87
76 """ 88 def chatWidget(self):
77 Public method to get a reference to the server. 89 """
78 90 Public method to get a reference to the chat widget.
79 @return reference to the server object (CooperationServer) 91
80 """ 92 @return reference to the chat widget (ChatWidget)
81 return self.__server 93 """
94 return self.__chatWidget
82 95
83 def sendMessage(self, message): 96 def sendMessage(self, message):
84 """ 97 """
85 Public method to send a message. 98 Public method to send a message.
86 99
97 """ 110 """
98 Public method to get the nick name. 111 Public method to get the nick name.
99 112
100 @return nick name (string) 113 @return nick name (string)
101 """ 114 """
102 return "{0}@{1}:{2}".format( 115 return "{0}@{1}@{2}".format(
103 self.__username, 116 self.__username,
104 QHostInfo.localHostName(), 117 QHostInfo.localHostName(),
105 self.__server.serverPort() 118 self.__servers[0].serverPort()
106 ) 119 )
107 120
108 def hasConnection(self, senderIp, senderPort=-1): 121 def hasConnection(self, senderIp, senderPort=-1):
109 """ 122 """
110 Public method to check for an existing connection. 123 Public method to check for an existing connection.
166 Private slot to handle a new connection. 179 Private slot to handle a new connection.
167 180
168 @param connection reference to the new connection (Connection) 181 @param connection reference to the new connection (Connection)
169 """ 182 """
170 connection.setParent(self) 183 connection.setParent(self)
184 connection.setClient(self)
171 connection.setGreetingMessage(self.__username, 185 connection.setGreetingMessage(self.__username,
172 self.__server.serverPort()) 186 self.__servers[0].serverPort())
173 187
174 connection.error.connect(self.__connectionError) 188 connection.error.connect(self.__connectionError)
175 connection.disconnected.connect(self.__disconnected) 189 connection.disconnected.connect(self.__disconnected)
176 connection.readyForUse.connect(self.__readyForUse) 190 connection.readyForUse.connect(self.__readyForUse)
177 connection.rejected.connect(self.__connectionRejected) 191 connection.rejected.connect(self.__connectionRejected)
252 reqConnection = self.sender() 266 reqConnection = self.sender()
253 participants = [] 267 participants = []
254 for connectionList in self.__peers.values(): 268 for connectionList in self.__peers.values():
255 for connection in connectionList: 269 for connection in connectionList:
256 if connection != reqConnection: 270 if connection != reqConnection:
257 participants.append("{0}:{1}".format( 271 participants.append("{0}@{1}".format(
258 connection.peerAddress().toString(), connection.serverPort())) 272 connection.peerAddress().toString(), connection.serverPort()))
259 reqConnection.sendParticipants(participants) 273 reqConnection.sendParticipants(participants)
260 274
261 def __processParticipants(self, participants): 275 def __processParticipants(self, participants):
262 """ 276 """
263 Private slot to handle the receipt of a list of participants. 277 Private slot to handle the receipt of a list of participants.
264 278
265 @param participants list of participants (list of strings of "host:port") 279 @param participants list of participants (list of strings of "host:port")
266 """ 280 """
267 for participant in participants: 281 for participant in participants:
268 host, port = participant.split(":") 282 host, port = participant.split("@")
269 port = int(port) 283 port = int(port)
270 284
271 if port == 0: 285 if port == 0:
272 msg = self.trUtf8("Illegal address: {0}:{1}\n").format(host, port) 286 msg = self.trUtf8("Illegal address: {0}@{1}\n").format(host, port)
273 self.connectionError.emit(msg) 287 self.connectionError.emit(msg)
274 else: 288 else:
275 if not self.hasConnection(QHostAddress(host), port): 289 if not self.hasConnection(QHostAddress(host), port):
276 connection = Connection(self) 290 connection = Connection(self)
277 self.__newConnection(connection) 291 self.__newConnection(connection)
295 Public method to get a list of connection given a nick name. 309 Public method to get a list of connection given a nick name.
296 310
297 @param nick nick name in the format of self.nickName() (string) 311 @param nick nick name in the format of self.nickName() (string)
298 @return list of references to the connection objects (list of Connection) 312 @return list of references to the connection objects (list of Connection)
299 """ 313 """
300 if "@" not in nick or ":" not in nick: 314 if "@" not in nick:
301 # nick given in wrong format 315 # nick given in wrong format
302 return [] 316 return []
303 317
304 user, host = nick.split(":")[0].split("@") 318 user, host, port = nick.split("@")
305 senderIp = QHostAddress(host) 319 senderIp = QHostAddress(host)
306 320
307 if senderIp not in self.__peers: 321 if senderIp not in self.__peers:
308 return [] 322 return []
309 323
323 Public method to ban a user by its nick name. 337 Public method to ban a user by its nick name.
324 338
325 @param nick nick name in the format of self.nickName() (string) 339 @param nick nick name in the format of self.nickName() (string)
326 """ 340 """
327 Preferences.syncPreferences() 341 Preferences.syncPreferences()
328 user = nick.split(":")[0] 342 user = nick.split("@")[0]
329 bannedUsers = Preferences.getCooperation("BannedUsers")[:] 343 bannedUsers = Preferences.getCooperation("BannedUsers")[:]
330 if user not in bannedUsers: 344 if user not in bannedUsers:
331 bannedUsers.append(user) 345 bannedUsers.append(user)
332 Preferences.setCooperation("BannedUsers", bannedUsers) 346 Preferences.setCooperation("BannedUsers", bannedUsers)
333 347
337 351
338 @param nick nick name in the format of self.nickName() (string) 352 @param nick nick name in the format of self.nickName() (string)
339 """ 353 """
340 self.banUser(nick) 354 self.banUser(nick)
341 self.kickUser(nick) 355 self.kickUser(nick)
356
357 def startListening(self, port=-1):
358 """
359 Public method to start listening for new connections.
360
361 @param port port to listen on (integer)
362 @return tuple giving a flag indicating success (boolean) and
363 the port the server listens on
364 """
365 if self.__servers:
366 # do first server and determine free port
367 res, port = self.__servers[0].startListening(port, True)
368 if res and len(self.__servers) > 1:
369 for server in self.__servers[1:]:
370 res, port = server.startListening(port, False)
371 if not res:
372 self.__serversErrorString = server.errorString()
373 else:
374 self.__serversErrorString = self.__servers[0].errorString()
375 else:
376 res = False
377 self.__serversErrorString = self.trUtf8("No servers present.")
378
379 if res:
380 self.__serversErrorString = ""
381 self.__listening = res
382 return res, port
383
384 def isListening(self):
385 """
386 Public method to check, if the client is listening for connections.
387
388 @return flag indicating the listening state (boolean)
389 """
390 return self.__listening
391
392 def close(self):
393 """
394 Public method to close all connections and stop listening.
395 """
396 for server in self.__servers:
397 server.close()
398 self.__listening = False
399
400 def errorString(self):
401 """
402 Public method to get a human readable error message about the last server error.
403
404 @return human readable error message about the last server error (string)
405 """
406 return self.__serversErrorString

eric ide

mercurial