Cooperation/Connection.py

changeset 945
8cd4d08fa9f6
parent 791
9ec2ac20e54e
child 1131
7781e396c903
equal deleted inserted replaced
944:1b59c4ba121e 945:8cd4d08fa9f6
12 12
13 from E5Gui import E5MessageBox 13 from E5Gui import E5MessageBox
14 14
15 import Preferences 15 import Preferences
16 16
17 MaxBufferSize = 1024 * 1024 17 MaxBufferSize = 1024 * 1024
18 TransferTimeout = 30 * 1000 18 TransferTimeout = 30 * 1000
19 PongTimeout = 60 * 1000 19 PongTimeout = 60 * 1000
20 PingInterval = 5 * 1000 20 PingInterval = 5 * 1000
21 SeparatorToken = '|||' 21 SeparatorToken = '|||'
22
22 23
23 class Connection(QTcpSocket): 24 class Connection(QTcpSocket):
24 """ 25 """
25 Class representing a peer connection. 26 Class representing a peer connection.
26 27
27 @signal readyForUse() emitted when the connection is ready for use 28 @signal readyForUse() emitted when the connection is ready for use
28 @signal newMessage(user, message) emitted after a new message has 29 @signal newMessage(user, message) emitted after a new message has
29 arrived (string, string) 30 arrived (string, string)
30 @signal getParticipants() emitted after a get participants message has arrived 31 @signal getParticipants() emitted after a get participants message has arrived
31 @signal participants(participants) emitted after the list of participants has 32 @signal participants(participants) emitted after the list of participants has
32 arrived (list of strings of "host:port") 33 arrived (list of strings of "host:port")
33 """ 34 """
34 WaitingForGreeting = 0 35 WaitingForGreeting = 0
35 ReadingGreeting = 1 36 ReadingGreeting = 1
36 ReadyForUse = 2 37 ReadyForUse = 2
37 38
38 PlainText = 0 39 PlainText = 0
39 Ping = 1 40 Ping = 1
40 Pong = 2 41 Pong = 2
41 Greeting = 3 42 Greeting = 3
42 GetParticipants = 4 43 GetParticipants = 4
43 Participants = 5 44 Participants = 5
44 Editor = 6 45 Editor = 6
45 Undefined = 99 46 Undefined = 99
46 47
47 ProtocolMessage = "MESSAGE" 48 ProtocolMessage = "MESSAGE"
48 ProtocolPing = "PING" 49 ProtocolPing = "PING"
49 ProtocolPong = "PONG" 50 ProtocolPong = "PONG"
50 ProtocolGreeting = "GREETING" 51 ProtocolGreeting = "GREETING"
51 ProtocolGetParticipants = "GET_PARTICIPANTS" 52 ProtocolGetParticipants = "GET_PARTICIPANTS"
52 ProtocolParticipants = "PARTICIPANTS" 53 ProtocolParticipants = "PARTICIPANTS"
53 ProtocolEditor = "EDITOR" 54 ProtocolEditor = "EDITOR"
54 55
55 readyForUse = pyqtSignal() 56 readyForUse = pyqtSignal()
56 newMessage = pyqtSignal(str, str) 57 newMessage = pyqtSignal(str, str)
57 getParticipants = pyqtSignal() 58 getParticipants = pyqtSignal()
58 participants = pyqtSignal(list) 59 participants = pyqtSignal(list)
59 editorCommand = pyqtSignal(str, str, str) 60 editorCommand = pyqtSignal(str, str, str)
60 rejected = pyqtSignal(str) 61 rejected = pyqtSignal(str)
61 62
62 def __init__(self, parent = None): 63 def __init__(self, parent=None):
63 """ 64 """
64 Constructor 65 Constructor
65 66
66 @param parent referenec to the parent object (QObject) 67 @param parent referenec to the parent object (QObject)
67 """ 68 """
155 if self.__buffer.size() != self.__numBytesForCurrentDataType: 156 if self.__buffer.size() != self.__numBytesForCurrentDataType:
156 self.abort() 157 self.abort()
157 return 158 return
158 159
159 try: 160 try:
160 user, serverPort = str(self.__buffer, encoding = "utf-8").split(":") 161 user, serverPort = str(self.__buffer, encoding="utf-8").split(":")
161 except ValueError: 162 except ValueError:
162 self.abort() 163 self.abort()
163 return 164 return
164 self.__serverPort = int(serverPort) 165 self.__serverPort = int(serverPort)
165 166
166 self.__username = "{0}@{1}:{2}".format( 167 self.__username = "{0}@{1}:{2}".format(
167 user, 168 user,
168 self.peerAddress().toString(), 169 self.peerAddress().toString(),
169 self.peerPort() 170 self.peerPort()
170 ) 171 )
171 self.__currentDataType = Connection.Undefined 172 self.__currentDataType = Connection.Undefined
172 self.__numBytesForCurrentDataType = 0 173 self.__numBytesForCurrentDataType = 0
173 self.__buffer.clear() 174 self.__buffer.clear()
175 if not self.isValid(): 176 if not self.isValid():
176 self.abort() 177 self.abort()
177 return 178 return
178 179
179 bannedName = "{0}@{1}".format( 180 bannedName = "{0}@{1}".format(
180 user, 181 user,
181 self.peerAddress().toString() 182 self.peerAddress().toString()
182 ) 183 )
183 Preferences.syncPreferences() 184 Preferences.syncPreferences()
184 if bannedName in Preferences.getCooperation("BannedUsers"): 185 if bannedName in Preferences.getCooperation("BannedUsers"):
185 self.rejected.emit( 186 self.rejected.emit(
188 self.abort() 189 self.abort()
189 return 190 return
190 191
191 if self.__serverPort != self.peerPort() and \ 192 if self.__serverPort != self.peerPort() and \
192 not Preferences.getCooperation("AutoAcceptConnections"): 193 not Preferences.getCooperation("AutoAcceptConnections"):
193 # don't ask for reverse connections or 194 # don't ask for reverse connections or
194 # if we shall accept automatically 195 # if we shall accept automatically
195 res = E5MessageBox.yesNo(None, 196 res = E5MessageBox.yesNo(None,
196 self.trUtf8("New Connection"), 197 self.trUtf8("New Connection"),
197 self.trUtf8("""<p>Accept connection from """ 198 self.trUtf8("""<p>Accept connection from """
198 """<strong>{0}@{1}</strong>?</p>""").format( 199 """<strong>{0}@{1}</strong>?</p>""").format(
199 user, self.peerAddress().toString()), 200 user, self.peerAddress().toString()),
200 yesDefault = True) 201 yesDefault=True)
201 if not res: 202 if not res:
202 self.abort() 203 self.abort()
203 return 204 return
204 205
205 if not self.__isGreetingMessageSent: 206 if not self.__isGreetingMessageSent:
238 data = QByteArray("{0}{1}{2}{1}".format( 239 data = QByteArray("{0}{1}{2}{1}".format(
239 Connection.ProtocolGreeting, SeparatorToken, greeting.size())) + greeting 240 Connection.ProtocolGreeting, SeparatorToken, greeting.size())) + greeting
240 if self.write(data) == data.size(): 241 if self.write(data) == data.size():
241 self.__isGreetingMessageSent = True 242 self.__isGreetingMessageSent = True
242 243
243 def __readDataIntoBuffer(self, maxSize = MaxBufferSize): 244 def __readDataIntoBuffer(self, maxSize=MaxBufferSize):
244 """ 245 """
245 Private method to read some data into the buffer. 246 Private method to read some data into the buffer.
246 247
247 @param maxSize maximum size of data to read (integer) 248 @param maxSize maximum size of data to read (integer)
248 @return size of data read (integer) 249 @return size of data read (integer)
344 if self.__buffer.size() != self.__numBytesForCurrentDataType: 345 if self.__buffer.size() != self.__numBytesForCurrentDataType:
345 self.abort() 346 self.abort()
346 return 347 return
347 348
348 if self.__currentDataType == Connection.PlainText: 349 if self.__currentDataType == Connection.PlainText:
349 self.newMessage.emit(self.__username, str(self.__buffer, encoding = "utf-8")) 350 self.newMessage.emit(self.__username, str(self.__buffer, encoding="utf-8"))
350 elif self.__currentDataType == Connection.Ping: 351 elif self.__currentDataType == Connection.Ping:
351 self.write("{0}{1}1{1}p".format(Connection.ProtocolPong, SeparatorToken)) 352 self.write("{0}{1}1{1}p".format(Connection.ProtocolPong, SeparatorToken))
352 elif self.__currentDataType == Connection.Pong: 353 elif self.__currentDataType == Connection.Pong:
353 self.__pongTime.restart() 354 self.__pongTime.restart()
354 elif self.__currentDataType == Connection.GetParticipants: 355 elif self.__currentDataType == Connection.GetParticipants:
355 self.getParticipants.emit() 356 self.getParticipants.emit()
356 elif self.__currentDataType == Connection.Participants: 357 elif self.__currentDataType == Connection.Participants:
357 msg = str(self.__buffer, encoding = "utf-8") 358 msg = str(self.__buffer, encoding="utf-8")
358 if msg == "<empty>": 359 if msg == "<empty>":
359 participantsList = [] 360 participantsList = []
360 else: 361 else:
361 participantsList = msg.split(SeparatorToken) 362 participantsList = msg.split(SeparatorToken)
362 self.participants.emit(participantsList[:]) 363 self.participants.emit(participantsList[:])
363 elif self.__currentDataType == Connection.Editor: 364 elif self.__currentDataType == Connection.Editor:
364 hash, fn, msg = str(self.__buffer, encoding = "utf-8").split(SeparatorToken) 365 hash, fn, msg = str(self.__buffer, encoding="utf-8").split(SeparatorToken)
365 self.editorCommand.emit(hash, fn, msg) 366 self.editorCommand.emit(hash, fn, msg)
366 367
367 self.__currentDataType = Connection.Undefined 368 self.__currentDataType = Connection.Undefined
368 self.__numBytesForCurrentDataType = 0 369 self.__numBytesForCurrentDataType = 0
369 self.__buffer.clear() 370 self.__buffer.clear()
394 def sendEditorCommand(self, projectHash, filename, message): 395 def sendEditorCommand(self, projectHash, filename, message):
395 """ 396 """
396 Public method to send an editor command. 397 Public method to send an editor command.
397 398
398 @param projectHash hash of the project (string) 399 @param projectHash hash of the project (string)
399 @param filename project relative universal file name of 400 @param filename project relative universal file name of
400 the sending editor (string) 401 the sending editor (string)
401 @param message editor command to be sent (string) 402 @param message editor command to be sent (string)
402 """ 403 """
403 msg = QByteArray("{0}{1}{2}{1}{3}".format( 404 msg = QByteArray("{0}{1}{2}{1}{3}".format(
404 projectHash, SeparatorToken, filename, message).encode("utf-8")) 405 projectHash, SeparatorToken, filename, message).encode("utf-8"))

eric ide

mercurial