32 """ |
32 """ |
33 Class representing a peer connection. |
33 Class representing a peer connection. |
34 |
34 |
35 @signal readyForUse() emitted when the connection is ready for use |
35 @signal readyForUse() emitted when the connection is ready for use |
36 @signal newMessage(user, message) emitted after a new message has |
36 @signal newMessage(user, message) emitted after a new message has |
37 arrived (string, string) |
37 arrived (string, string) |
38 @signal getParticipants() emitted after a get participants message has arrived |
38 @signal getParticipants() emitted after a get participants message has |
39 @signal participants(participants) emitted after the list of participants has |
39 arrived |
40 arrived (list of strings of "host:port") |
40 @signal participants(participants) emitted after the list of participants |
|
41 has arrived (list of strings of "host:port") |
41 """ |
42 """ |
42 WaitingForGreeting = 0 |
43 WaitingForGreeting = 0 |
43 ReadingGreeting = 1 |
44 ReadingGreeting = 1 |
44 ReadyForUse = 2 |
45 ReadyForUse = 2 |
45 |
46 |
121 def setGreetingMessage(self, message, serverPort): |
122 def setGreetingMessage(self, message, serverPort): |
122 """ |
123 """ |
123 Public method to set the greeting message. |
124 Public method to set the greeting message. |
124 |
125 |
125 @param message greeting message (string) |
126 @param message greeting message (string) |
|
127 @param serverPort port number to include in the message (integer) |
126 """ |
128 """ |
127 self.__greetingMessage = "{0}:{1}".format(message, serverPort) |
129 self.__greetingMessage = "{0}:{1}".format(message, serverPort) |
128 |
130 |
129 def sendMessage(self, message): |
131 def sendMessage(self, message): |
130 """ |
132 """ |
166 |
168 |
167 if self.__state == Connection.ReadingGreeting: |
169 if self.__state == Connection.ReadingGreeting: |
168 if not self.__hasEnoughData(): |
170 if not self.__hasEnoughData(): |
169 return |
171 return |
170 |
172 |
171 self.__buffer = QByteArray(self.read(self.__numBytesForCurrentDataType)) |
173 self.__buffer = QByteArray( |
|
174 self.read(self.__numBytesForCurrentDataType)) |
172 if self.__buffer.size() != self.__numBytesForCurrentDataType: |
175 if self.__buffer.size() != self.__numBytesForCurrentDataType: |
173 self.abort() |
176 self.abort() |
174 return |
177 return |
175 |
178 |
176 try: |
179 try: |
177 user, serverPort = str(self.__buffer, encoding="utf-8").split(":") |
180 user, serverPort = \ |
|
181 str(self.__buffer, encoding="utf-8").split(":") |
178 except ValueError: |
182 except ValueError: |
179 self.abort() |
183 self.abort() |
180 return |
184 return |
181 self.__serverPort = int(serverPort) |
185 self.__serverPort = int(serverPort) |
182 |
186 |
198 user, |
202 user, |
199 hostInfo.hostName(), |
203 hostInfo.hostName(), |
200 ) |
204 ) |
201 Preferences.syncPreferences() |
205 Preferences.syncPreferences() |
202 if bannedName in Preferences.getCooperation("BannedUsers"): |
206 if bannedName in Preferences.getCooperation("BannedUsers"): |
203 self.rejected.emit( |
207 self.rejected.emit(self.trUtf8( |
204 self.trUtf8("* Connection attempted by banned user '{0}'.")\ |
208 "* Connection attempted by banned user '{0}'.") |
205 .format(bannedName)) |
209 .format(bannedName)) |
206 self.abort() |
210 self.abort() |
207 return |
211 return |
208 |
212 |
209 if self.__serverPort != self.peerPort() and \ |
213 if self.__serverPort != self.peerPort() and \ |
210 not Preferences.getCooperation("AutoAcceptConnections"): |
214 not Preferences.getCooperation("AutoAcceptConnections"): |
221 return |
225 return |
222 |
226 |
223 if self.__client is not None: |
227 if self.__client is not None: |
224 chatWidget = self.__client.chatWidget() |
228 chatWidget = self.__client.chatWidget() |
225 if chatWidget is not None and not chatWidget.isVisible(): |
229 if chatWidget is not None and not chatWidget.isVisible(): |
226 e5App().getObject("UserInterface").activateCooperationViewer() |
230 e5App().getObject( |
|
231 "UserInterface").activateCooperationViewer() |
227 |
232 |
228 if not self.__isGreetingMessageSent: |
233 if not self.__isGreetingMessageSent: |
229 self.__sendGreetingMessage() |
234 self.__sendGreetingMessage() |
230 |
235 |
231 self.__pingTimer.start() |
236 self.__pingTimer.start() |
249 """ |
254 """ |
250 if self.__pongTime.elapsed() > PongTimeout: |
255 if self.__pongTime.elapsed() > PongTimeout: |
251 self.abort() |
256 self.abort() |
252 return |
257 return |
253 |
258 |
254 self.write("{0}{1}1{1}p".format(Connection.ProtocolPing, SeparatorToken)) |
259 self.write("{0}{1}1{1}p".format( |
|
260 Connection.ProtocolPing, SeparatorToken)) |
255 |
261 |
256 def __sendGreetingMessage(self): |
262 def __sendGreetingMessage(self): |
257 """ |
263 """ |
258 Private slot to send a greeting message. |
264 Private slot to send a greeting message. |
259 """ |
265 """ |
260 greeting = QByteArray(self.__greetingMessage.encode("utf-8")) |
266 greeting = QByteArray(self.__greetingMessage.encode("utf-8")) |
261 data = QByteArray("{0}{1}{2}{1}".format( |
267 data = QByteArray("{0}{1}{2}{1}".format( |
262 Connection.ProtocolGreeting, SeparatorToken, greeting.size())) + greeting |
268 Connection.ProtocolGreeting, SeparatorToken, greeting.size())) + \ |
|
269 greeting |
263 if self.write(data) == data.size(): |
270 if self.write(data) == data.size(): |
264 self.__isGreetingMessageSent = True |
271 self.__isGreetingMessageSent = True |
265 |
272 |
266 def __readDataIntoBuffer(self, maxSize=MaxBufferSize): |
273 def __readDataIntoBuffer(self, maxSize=MaxBufferSize): |
267 """ |
274 """ |
334 self.__currentDataType = Connection.Undefined |
341 self.__currentDataType = Connection.Undefined |
335 self.abort() |
342 self.abort() |
336 return False |
343 return False |
337 |
344 |
338 self.__buffer.clear() |
345 self.__buffer.clear() |
339 self.__numBytesForCurrentDataType = self.__dataLengthForCurrentDataType() |
346 self.__numBytesForCurrentDataType = \ |
|
347 self.__dataLengthForCurrentDataType() |
340 return True |
348 return True |
341 |
349 |
342 def __hasEnoughData(self): |
350 def __hasEnoughData(self): |
343 """ |
351 """ |
344 Private method to check, if enough data is available. |
352 Private method to check, if enough data is available. |
348 if self.__transferTimerId: |
356 if self.__transferTimerId: |
349 self.killTimer(self.__transferTimerId) |
357 self.killTimer(self.__transferTimerId) |
350 self.__transferTimerId = 0 |
358 self.__transferTimerId = 0 |
351 |
359 |
352 if self.__numBytesForCurrentDataType <= 0: |
360 if self.__numBytesForCurrentDataType <= 0: |
353 self.__numBytesForCurrentDataType = self.__dataLengthForCurrentDataType() |
361 self.__numBytesForCurrentDataType = \ |
|
362 self.__dataLengthForCurrentDataType() |
354 |
363 |
355 if self.bytesAvailable() < self.__numBytesForCurrentDataType or \ |
364 if self.bytesAvailable() < self.__numBytesForCurrentDataType or \ |
356 self.__numBytesForCurrentDataType <= 0: |
365 self.__numBytesForCurrentDataType <= 0: |
357 self.__transferTimerId = self.startTimer(TransferTimeout) |
366 self.__transferTimerId = self.startTimer(TransferTimeout) |
358 return False |
367 return False |
361 |
370 |
362 def __processData(self): |
371 def __processData(self): |
363 """ |
372 """ |
364 Private method to process the received data. |
373 Private method to process the received data. |
365 """ |
374 """ |
366 self.__buffer = QByteArray(self.read(self.__numBytesForCurrentDataType)) |
375 self.__buffer = QByteArray( |
|
376 self.read(self.__numBytesForCurrentDataType)) |
367 if self.__buffer.size() != self.__numBytesForCurrentDataType: |
377 if self.__buffer.size() != self.__numBytesForCurrentDataType: |
368 self.abort() |
378 self.abort() |
369 return |
379 return |
370 |
380 |
371 if self.__currentDataType == Connection.PlainText: |
381 if self.__currentDataType == Connection.PlainText: |
372 self.newMessage.emit(self.__username, str(self.__buffer, encoding="utf-8")) |
382 self.newMessage.emit( |
|
383 self.__username, str(self.__buffer, encoding="utf-8")) |
373 elif self.__currentDataType == Connection.Ping: |
384 elif self.__currentDataType == Connection.Ping: |
374 self.write("{0}{1}1{1}p".format(Connection.ProtocolPong, SeparatorToken)) |
385 self.write("{0}{1}1{1}p".format( |
|
386 Connection.ProtocolPong, SeparatorToken)) |
375 elif self.__currentDataType == Connection.Pong: |
387 elif self.__currentDataType == Connection.Pong: |
376 self.__pongTime.restart() |
388 self.__pongTime.restart() |
377 elif self.__currentDataType == Connection.GetParticipants: |
389 elif self.__currentDataType == Connection.GetParticipants: |
378 self.getParticipants.emit() |
390 self.getParticipants.emit() |
379 elif self.__currentDataType == Connection.Participants: |
391 elif self.__currentDataType == Connection.Participants: |
382 participantsList = [] |
394 participantsList = [] |
383 else: |
395 else: |
384 participantsList = msg.split(SeparatorToken) |
396 participantsList = msg.split(SeparatorToken) |
385 self.participants.emit(participantsList[:]) |
397 self.participants.emit(participantsList[:]) |
386 elif self.__currentDataType == Connection.Editor: |
398 elif self.__currentDataType == Connection.Editor: |
387 hash, fn, msg = str(self.__buffer, encoding="utf-8").split(SeparatorToken) |
399 hash, fn, msg = \ |
|
400 str(self.__buffer, encoding="utf-8").split(SeparatorToken) |
388 self.editorCommand.emit(hash, fn, msg) |
401 self.editorCommand.emit(hash, fn, msg) |
389 |
402 |
390 self.__currentDataType = Connection.Undefined |
403 self.__currentDataType = Connection.Undefined |
391 self.__numBytesForCurrentDataType = 0 |
404 self.__numBytesForCurrentDataType = 0 |
392 self.__buffer.clear() |
405 self.__buffer.clear() |
394 def sendGetParticipants(self): |
407 def sendGetParticipants(self): |
395 """ |
408 """ |
396 Public method to request a list of participants. |
409 Public method to request a list of participants. |
397 """ |
410 """ |
398 self.write( |
411 self.write( |
399 "{0}{1}1{1}l".format(Connection.ProtocolGetParticipants, SeparatorToken) |
412 "{0}{1}1{1}l".format( |
|
413 Connection.ProtocolGetParticipants, SeparatorToken) |
400 ) |
414 ) |
401 |
415 |
402 def sendParticipants(self, participants): |
416 def sendParticipants(self, participants): |
403 """ |
417 """ |
404 Public method to send the list of participants. |
418 Public method to send the list of participants. |
405 |
419 |
406 @param participants list of participants (list of strings of "host:port") |
420 @param participants list of participants (list of strings of |
|
421 "host:port") |
407 """ |
422 """ |
408 if participants: |
423 if participants: |
409 message = SeparatorToken.join(participants) |
424 message = SeparatorToken.join(participants) |
410 else: |
425 else: |
411 message = "<empty>" |
426 message = "<empty>" |
433 """ |
448 """ |
434 Private slot to handle the connection being dropped. |
449 Private slot to handle the connection being dropped. |
435 """ |
450 """ |
436 self.__pingTimer.stop() |
451 self.__pingTimer.stop() |
437 if self.__state == Connection.WaitingForGreeting: |
452 if self.__state == Connection.WaitingForGreeting: |
438 self.rejected.emit(self.trUtf8("* Connection to {0}:{1} refused.").format( |
453 self.rejected.emit(self.trUtf8( |
|
454 "* Connection to {0}:{1} refused.").format( |
439 self.peerName(), self.peerPort())) |
455 self.peerName(), self.peerPort())) |